Considere el dataset proporcionado que contiene información sobre distintos sensores corporales y cuyo objetivo es predecir la postura corporal durante la realización de un ejercicio. Los distintos tipos de posturas están codificados en una variable llamada classe con las letras de la A a la E, representando, respectivamente:
Como vamos a tratar el problema como uno de aprendizaje no supervisado, es conveniente asegurarse de no incluir el atributo de clase entre las características con las que se entrene el modelo
El ejercicio consiste, por tanto, en construir un modelo de segmentación que intente capturar la estructura de grupos existente en el conjunto de datos original.
Se sugiere un rápido análisis exploratorio del conjunto de datos para determinar si:
Aparte de lo anterior, conviene explorar la posibilidad de usar distintos modelos de aprendizaje, que pueden ser comparados de acuerdo con alguna métrica de calidad. En este caso, y dado que se dispone de las etiquetas reales de los datos, se podría usar una métrica de evaluación externa. En cualquier caso, y al tratarse de un conjunto de datos de un volumen no despreciable, se recomienda cuidado al calcular muchas métricas de evaluación, ya que algunas pueden tardar mucho tiempo en calcularse. Con el objetivo de cubrir el proceso total de análisis de un problema de estas características, se recomienda calcular sólo una o dos, aunque en un escenario real, tal y como vimos en clase, podría ser recomendable calcular más.
library(corrplot) # Matriz de correlaciones
library(clusterSim)
library(tidyverse) # Cargo tidyverse después de clusterSim porque el paquete Mass de clusterSim masks 'dplyr::select()'
library(fpc)
library(factoextra)
library(NbClust)
library(caret)
library(cluster)
library(mclust)
library(dbscan)
library(ggplot2)
library(plotly)
Importamos los datos y visualizamos una muestra.
df <- read_csv("../data/datos_train.csv")
knitr::kable(head(df))
| user_name | raw_timestamp_part_1 | raw_timestamp_part_2 | cvtd_timestamp | roll_belt | pitch_belt | yaw_belt | total_accel_belt | kurtosis_roll_belt | kurtosis_picth_belt | kurtosis_yaw_belt | skewness_roll_belt | skewness_roll_belt.1 | skewness_yaw_belt | max_roll_belt | max_picth_belt | max_yaw_belt | min_roll_belt | min_pitch_belt | min_yaw_belt | amplitude_roll_belt | amplitude_pitch_belt | amplitude_yaw_belt | var_total_accel_belt | avg_roll_belt | stddev_roll_belt | var_roll_belt | avg_pitch_belt | stddev_pitch_belt | var_pitch_belt | avg_yaw_belt | stddev_yaw_belt | var_yaw_belt | gyros_belt_x | gyros_belt_y | gyros_belt_z | accel_belt_x | accel_belt_y | accel_belt_z | magnet_belt_x | magnet_belt_y | magnet_belt_z | roll_arm | pitch_arm | yaw_arm | total_accel_arm | var_accel_arm | avg_roll_arm | stddev_roll_arm | var_roll_arm | avg_pitch_arm | stddev_pitch_arm | var_pitch_arm | avg_yaw_arm | stddev_yaw_arm | var_yaw_arm | gyros_arm_x | gyros_arm_y | gyros_arm_z | accel_arm_x | accel_arm_y | accel_arm_z | magnet_arm_x | magnet_arm_y | magnet_arm_z | kurtosis_roll_arm | kurtosis_picth_arm | kurtosis_yaw_arm | skewness_roll_arm | skewness_pitch_arm | skewness_yaw_arm | max_roll_arm | max_picth_arm | max_yaw_arm | min_roll_arm | min_pitch_arm | min_yaw_arm | amplitude_roll_arm | amplitude_pitch_arm | amplitude_yaw_arm | roll_dumbbell | pitch_dumbbell | yaw_dumbbell | kurtosis_roll_dumbbell | kurtosis_picth_dumbbell | kurtosis_yaw_dumbbell | skewness_roll_dumbbell | skewness_pitch_dumbbell | skewness_yaw_dumbbell | max_roll_dumbbell | max_picth_dumbbell | max_yaw_dumbbell | min_roll_dumbbell | min_pitch_dumbbell | min_yaw_dumbbell | amplitude_roll_dumbbell | amplitude_pitch_dumbbell | amplitude_yaw_dumbbell | total_accel_dumbbell | var_accel_dumbbell | avg_roll_dumbbell | stddev_roll_dumbbell | var_roll_dumbbell | avg_pitch_dumbbell | stddev_pitch_dumbbell | var_pitch_dumbbell | avg_yaw_dumbbell | stddev_yaw_dumbbell | var_yaw_dumbbell | gyros_dumbbell_x | gyros_dumbbell_y | gyros_dumbbell_z | accel_dumbbell_x | accel_dumbbell_y | accel_dumbbell_z | magnet_dumbbell_x | magnet_dumbbell_y | magnet_dumbbell_z | roll_forearm | pitch_forearm | yaw_forearm | kurtosis_roll_forearm | kurtosis_picth_forearm | kurtosis_yaw_forearm | skewness_roll_forearm | skewness_pitch_forearm | skewness_yaw_forearm | max_roll_forearm | max_picth_forearm | max_yaw_forearm | min_roll_forearm | min_pitch_forearm | min_yaw_forearm | amplitude_roll_forearm | amplitude_pitch_forearm | amplitude_yaw_forearm | total_accel_forearm | var_accel_forearm | avg_roll_forearm | stddev_roll_forearm | var_roll_forearm | avg_pitch_forearm | stddev_pitch_forearm | var_pitch_forearm | avg_yaw_forearm | stddev_yaw_forearm | var_yaw_forearm | gyros_forearm_x | gyros_forearm_y | gyros_forearm_z | accel_forearm_x | accel_forearm_y | accel_forearm_z | magnet_forearm_x | magnet_forearm_y | magnet_forearm_z | classe |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| carlitos | 1323084231 | 788290 | 05/12/2011 11:23 | 1.41 | 8.07 | -94.4 | 3 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0.00 | 0.00 | -0.02 | -21 | 4 | 22 | -3 | 599 | -313 | -128 | 22.5 | -161 | 34 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0.00 | 0.00 | -0.02 | -288 | 109 | -123 | -368 | 337 | 516 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 13.05217 | -70.49400 | -84.87394 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 37 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0 | -0.02 | 0.00 | -234 | 47 | -271 | -559 | 293 | -65 | 28.4 | -63.9 | -153 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 36 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0.03 | 0.00 | -0.02 | 192 | 203 | -215 | -17 | 654 | 476 | A |
| carlitos | 1323084231 | 808298 | 05/12/2011 11:23 | 1.41 | 8.07 | -94.4 | 3 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0.02 | 0.00 | -0.02 | -22 | 4 | 22 | -7 | 608 | -311 | -128 | 22.5 | -161 | 34 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0.02 | -0.02 | -0.02 | -290 | 110 | -125 | -369 | 337 | 513 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 13.13074 | -70.63751 | -84.71065 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 37 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0 | -0.02 | 0.00 | -233 | 47 | -269 | -555 | 296 | -64 | 28.3 | -63.9 | -153 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 36 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0.02 | 0.00 | -0.02 | 192 | 203 | -216 | -18 | 661 | 473 | A |
| carlitos | 1323084231 | 820366 | 05/12/2011 11:23 | 1.42 | 8.07 | -94.4 | 3 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0.00 | 0.00 | -0.02 | -20 | 5 | 23 | -2 | 600 | -305 | -128 | 22.5 | -161 | 34 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0.02 | -0.02 | -0.02 | -289 | 110 | -126 | -368 | 344 | 513 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 12.85075 | -70.27812 | -85.14078 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 37 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0 | -0.02 | 0.00 | -232 | 46 | -270 | -561 | 298 | -63 | 28.3 | -63.9 | -152 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 36 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0.03 | -0.02 | 0.00 | 196 | 204 | -213 | -18 | 658 | 469 | A |
| carlitos | 1323084232 | 120339 | 05/12/2011 11:23 | 1.48 | 8.05 | -94.4 | 3 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0.02 | 0.00 | -0.03 | -22 | 3 | 21 | -6 | 604 | -310 | -128 | 22.1 | -161 | 34 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0.02 | -0.03 | 0.02 | -289 | 111 | -123 | -372 | 344 | 512 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 13.43120 | -70.39379 | -84.87363 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 37 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0 | -0.02 | -0.02 | -232 | 48 | -269 | -552 | 303 | -60 | 28.1 | -63.9 | -152 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 36 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0.02 | -0.02 | 0.00 | 189 | 206 | -214 | -16 | 658 | 469 | A |
| carlitos | 1323084232 | 196328 | 05/12/2011 11:23 | 1.48 | 8.07 | -94.4 | 3 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0.02 | 0.02 | -0.02 | -21 | 2 | 24 | -6 | 600 | -302 | -128 | 22.1 | -161 | 34 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0.00 | -0.03 | 0.00 | -289 | 111 | -123 | -374 | 337 | 506 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 13.37872 | -70.42856 | -84.85306 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 37 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0 | -0.02 | 0.00 | -233 | 48 | -270 | -554 | 292 | -68 | 28.0 | -63.9 | -152 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 36 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0.02 | 0.00 | -0.02 | 189 | 206 | -214 | -17 | 655 | 473 | A |
| carlitos | 1323084232 | 304277 | 05/12/2011 11:23 | 1.45 | 8.06 | -94.4 | 3 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0.02 | 0.00 | -0.02 | -21 | 4 | 21 | 0 | 603 | -312 | -128 | 22.0 | -161 | 34 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0.02 | -0.03 | 0.00 | -289 | 111 | -122 | -369 | 342 | 513 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 13.38246 | -70.81759 | -84.46500 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 37 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0 | -0.02 | 0.00 | -234 | 48 | -269 | -558 | 294 | -66 | 27.9 | -63.9 | -152 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 36 | NA | NA | NA | NA | NA | NA | NA | NA | NA | NA | 0.02 | -0.02 | -0.03 | 193 | 203 | -215 | -9 | 660 | 478 | A |
Observamos el tamaño del conjunto de datos y su estructura.
Número de filas (instancias):
nrow(df)
## [1] 19622
Número de columnas (variables):
ncol(df)
## [1] 157
Información y estructura del dataframe
str(df)
## tibble [19,622 x 157] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ user_name : chr [1:19622] "carlitos" "carlitos" "carlitos" "carlitos" ...
## $ raw_timestamp_part_1 : num [1:19622] 1.32e+09 1.32e+09 1.32e+09 1.32e+09 1.32e+09 ...
## $ raw_timestamp_part_2 : num [1:19622] 788290 808298 820366 120339 196328 ...
## $ cvtd_timestamp : chr [1:19622] "05/12/2011 11:23" "05/12/2011 11:23" "05/12/2011 11:23" "05/12/2011 11:23" ...
## $ roll_belt : num [1:19622] 1.41 1.41 1.42 1.48 1.48 1.45 1.42 1.42 1.43 1.45 ...
## $ pitch_belt : num [1:19622] 8.07 8.07 8.07 8.05 8.07 8.06 8.09 8.13 8.16 8.17 ...
## $ yaw_belt : num [1:19622] -94.4 -94.4 -94.4 -94.4 -94.4 -94.4 -94.4 -94.4 -94.4 -94.4 ...
## $ total_accel_belt : num [1:19622] 3 3 3 3 3 3 3 3 3 3 ...
## $ kurtosis_roll_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ kurtosis_picth_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ kurtosis_yaw_belt : logi [1:19622] NA NA NA NA NA NA ...
## $ skewness_roll_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ skewness_roll_belt.1 : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ skewness_yaw_belt : logi [1:19622] NA NA NA NA NA NA ...
## $ max_roll_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ max_picth_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ max_yaw_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ min_roll_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ min_pitch_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ min_yaw_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ amplitude_roll_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ amplitude_pitch_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ amplitude_yaw_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ var_total_accel_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ avg_roll_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ stddev_roll_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ var_roll_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ avg_pitch_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ stddev_pitch_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ var_pitch_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ avg_yaw_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ stddev_yaw_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ var_yaw_belt : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ gyros_belt_x : num [1:19622] 0 0.02 0 0.02 0.02 0.02 0.02 0.02 0.02 0.03 ...
## $ gyros_belt_y : num [1:19622] 0 0 0 0 0.02 0 0 0 0 0 ...
## $ gyros_belt_z : num [1:19622] -0.02 -0.02 -0.02 -0.03 -0.02 -0.02 -0.02 -0.02 -0.02 0 ...
## $ accel_belt_x : num [1:19622] -21 -22 -20 -22 -21 -21 -22 -22 -20 -21 ...
## $ accel_belt_y : num [1:19622] 4 4 5 3 2 4 3 4 2 4 ...
## $ accel_belt_z : num [1:19622] 22 22 23 21 24 21 21 21 24 22 ...
## $ magnet_belt_x : num [1:19622] -3 -7 -2 -6 -6 0 -4 -2 1 -3 ...
## $ magnet_belt_y : num [1:19622] 599 608 600 604 600 603 599 603 602 609 ...
## $ magnet_belt_z : num [1:19622] -313 -311 -305 -310 -302 -312 -311 -313 -312 -308 ...
## $ roll_arm : num [1:19622] -128 -128 -128 -128 -128 -128 -128 -128 -128 -128 ...
## $ pitch_arm : num [1:19622] 22.5 22.5 22.5 22.1 22.1 22 21.9 21.8 21.7 21.6 ...
## $ yaw_arm : num [1:19622] -161 -161 -161 -161 -161 -161 -161 -161 -161 -161 ...
## $ total_accel_arm : num [1:19622] 34 34 34 34 34 34 34 34 34 34 ...
## $ var_accel_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ avg_roll_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ stddev_roll_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ var_roll_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ avg_pitch_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ stddev_pitch_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ var_pitch_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ avg_yaw_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ stddev_yaw_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ var_yaw_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ gyros_arm_x : num [1:19622] 0 0.02 0.02 0.02 0 0.02 0 0.02 0.02 0.02 ...
## $ gyros_arm_y : num [1:19622] 0 -0.02 -0.02 -0.03 -0.03 -0.03 -0.03 -0.02 -0.03 -0.03 ...
## $ gyros_arm_z : num [1:19622] -0.02 -0.02 -0.02 0.02 0 0 0 0 -0.02 -0.02 ...
## $ accel_arm_x : num [1:19622] -288 -290 -289 -289 -289 -289 -289 -289 -288 -288 ...
## $ accel_arm_y : num [1:19622] 109 110 110 111 111 111 111 111 109 110 ...
## $ accel_arm_z : num [1:19622] -123 -125 -126 -123 -123 -122 -125 -124 -122 -124 ...
## $ magnet_arm_x : num [1:19622] -368 -369 -368 -372 -374 -369 -373 -372 -369 -376 ...
## $ magnet_arm_y : num [1:19622] 337 337 344 344 337 342 336 338 341 334 ...
## $ magnet_arm_z : num [1:19622] 516 513 513 512 506 513 509 510 518 516 ...
## $ kurtosis_roll_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ kurtosis_picth_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ kurtosis_yaw_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ skewness_roll_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ skewness_pitch_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ skewness_yaw_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ max_roll_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ max_picth_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ max_yaw_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ min_roll_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ min_pitch_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ min_yaw_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ amplitude_roll_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ amplitude_pitch_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ amplitude_yaw_arm : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ roll_dumbbell : num [1:19622] 13.1 13.1 12.9 13.4 13.4 ...
## $ pitch_dumbbell : num [1:19622] -70.5 -70.6 -70.3 -70.4 -70.4 ...
## $ yaw_dumbbell : num [1:19622] -84.9 -84.7 -85.1 -84.9 -84.9 ...
## $ kurtosis_roll_dumbbell : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ kurtosis_picth_dumbbell : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ kurtosis_yaw_dumbbell : logi [1:19622] NA NA NA NA NA NA ...
## $ skewness_roll_dumbbell : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ skewness_pitch_dumbbell : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ skewness_yaw_dumbbell : logi [1:19622] NA NA NA NA NA NA ...
## $ max_roll_dumbbell : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ max_picth_dumbbell : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ max_yaw_dumbbell : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ min_roll_dumbbell : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ min_pitch_dumbbell : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ min_yaw_dumbbell : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ amplitude_roll_dumbbell : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ amplitude_pitch_dumbbell: num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ amplitude_yaw_dumbbell : num [1:19622] NA NA NA NA NA NA NA NA NA NA ...
## $ total_accel_dumbbell : num [1:19622] 37 37 37 37 37 37 37 37 37 37 ...
## [list output truncated]
## - attr(*, "spec")=
## .. cols(
## .. user_name = col_character(),
## .. raw_timestamp_part_1 = col_double(),
## .. raw_timestamp_part_2 = col_double(),
## .. cvtd_timestamp = col_character(),
## .. roll_belt = col_double(),
## .. pitch_belt = col_double(),
## .. yaw_belt = col_double(),
## .. total_accel_belt = col_double(),
## .. kurtosis_roll_belt = col_double(),
## .. kurtosis_picth_belt = col_double(),
## .. kurtosis_yaw_belt = col_logical(),
## .. skewness_roll_belt = col_double(),
## .. skewness_roll_belt.1 = col_double(),
## .. skewness_yaw_belt = col_logical(),
## .. max_roll_belt = col_double(),
## .. max_picth_belt = col_double(),
## .. max_yaw_belt = col_double(),
## .. min_roll_belt = col_double(),
## .. min_pitch_belt = col_double(),
## .. min_yaw_belt = col_double(),
## .. amplitude_roll_belt = col_double(),
## .. amplitude_pitch_belt = col_double(),
## .. amplitude_yaw_belt = col_double(),
## .. var_total_accel_belt = col_double(),
## .. avg_roll_belt = col_double(),
## .. stddev_roll_belt = col_double(),
## .. var_roll_belt = col_double(),
## .. avg_pitch_belt = col_double(),
## .. stddev_pitch_belt = col_double(),
## .. var_pitch_belt = col_double(),
## .. avg_yaw_belt = col_double(),
## .. stddev_yaw_belt = col_double(),
## .. var_yaw_belt = col_double(),
## .. gyros_belt_x = col_double(),
## .. gyros_belt_y = col_double(),
## .. gyros_belt_z = col_double(),
## .. accel_belt_x = col_double(),
## .. accel_belt_y = col_double(),
## .. accel_belt_z = col_double(),
## .. magnet_belt_x = col_double(),
## .. magnet_belt_y = col_double(),
## .. magnet_belt_z = col_double(),
## .. roll_arm = col_double(),
## .. pitch_arm = col_double(),
## .. yaw_arm = col_double(),
## .. total_accel_arm = col_double(),
## .. var_accel_arm = col_double(),
## .. avg_roll_arm = col_double(),
## .. stddev_roll_arm = col_double(),
## .. var_roll_arm = col_double(),
## .. avg_pitch_arm = col_double(),
## .. stddev_pitch_arm = col_double(),
## .. var_pitch_arm = col_double(),
## .. avg_yaw_arm = col_double(),
## .. stddev_yaw_arm = col_double(),
## .. var_yaw_arm = col_double(),
## .. gyros_arm_x = col_double(),
## .. gyros_arm_y = col_double(),
## .. gyros_arm_z = col_double(),
## .. accel_arm_x = col_double(),
## .. accel_arm_y = col_double(),
## .. accel_arm_z = col_double(),
## .. magnet_arm_x = col_double(),
## .. magnet_arm_y = col_double(),
## .. magnet_arm_z = col_double(),
## .. kurtosis_roll_arm = col_double(),
## .. kurtosis_picth_arm = col_double(),
## .. kurtosis_yaw_arm = col_double(),
## .. skewness_roll_arm = col_double(),
## .. skewness_pitch_arm = col_double(),
## .. skewness_yaw_arm = col_double(),
## .. max_roll_arm = col_double(),
## .. max_picth_arm = col_double(),
## .. max_yaw_arm = col_double(),
## .. min_roll_arm = col_double(),
## .. min_pitch_arm = col_double(),
## .. min_yaw_arm = col_double(),
## .. amplitude_roll_arm = col_double(),
## .. amplitude_pitch_arm = col_double(),
## .. amplitude_yaw_arm = col_double(),
## .. roll_dumbbell = col_double(),
## .. pitch_dumbbell = col_double(),
## .. yaw_dumbbell = col_double(),
## .. kurtosis_roll_dumbbell = col_double(),
## .. kurtosis_picth_dumbbell = col_double(),
## .. kurtosis_yaw_dumbbell = col_logical(),
## .. skewness_roll_dumbbell = col_double(),
## .. skewness_pitch_dumbbell = col_double(),
## .. skewness_yaw_dumbbell = col_logical(),
## .. max_roll_dumbbell = col_double(),
## .. max_picth_dumbbell = col_double(),
## .. max_yaw_dumbbell = col_double(),
## .. min_roll_dumbbell = col_double(),
## .. min_pitch_dumbbell = col_double(),
## .. min_yaw_dumbbell = col_double(),
## .. amplitude_roll_dumbbell = col_double(),
## .. amplitude_pitch_dumbbell = col_double(),
## .. amplitude_yaw_dumbbell = col_double(),
## .. total_accel_dumbbell = col_double(),
## .. var_accel_dumbbell = col_double(),
## .. avg_roll_dumbbell = col_double(),
## .. stddev_roll_dumbbell = col_double(),
## .. var_roll_dumbbell = col_double(),
## .. avg_pitch_dumbbell = col_double(),
## .. stddev_pitch_dumbbell = col_double(),
## .. var_pitch_dumbbell = col_double(),
## .. avg_yaw_dumbbell = col_double(),
## .. stddev_yaw_dumbbell = col_double(),
## .. var_yaw_dumbbell = col_double(),
## .. gyros_dumbbell_x = col_double(),
## .. gyros_dumbbell_y = col_double(),
## .. gyros_dumbbell_z = col_double(),
## .. accel_dumbbell_x = col_double(),
## .. accel_dumbbell_y = col_double(),
## .. accel_dumbbell_z = col_double(),
## .. magnet_dumbbell_x = col_double(),
## .. magnet_dumbbell_y = col_double(),
## .. magnet_dumbbell_z = col_double(),
## .. roll_forearm = col_double(),
## .. pitch_forearm = col_double(),
## .. yaw_forearm = col_double(),
## .. kurtosis_roll_forearm = col_double(),
## .. kurtosis_picth_forearm = col_double(),
## .. kurtosis_yaw_forearm = col_logical(),
## .. skewness_roll_forearm = col_double(),
## .. skewness_pitch_forearm = col_double(),
## .. skewness_yaw_forearm = col_logical(),
## .. max_roll_forearm = col_double(),
## .. max_picth_forearm = col_double(),
## .. max_yaw_forearm = col_double(),
## .. min_roll_forearm = col_double(),
## .. min_pitch_forearm = col_double(),
## .. min_yaw_forearm = col_double(),
## .. amplitude_roll_forearm = col_double(),
## .. amplitude_pitch_forearm = col_double(),
## .. amplitude_yaw_forearm = col_double(),
## .. total_accel_forearm = col_double(),
## .. var_accel_forearm = col_double(),
## .. avg_roll_forearm = col_double(),
## .. stddev_roll_forearm = col_double(),
## .. var_roll_forearm = col_double(),
## .. avg_pitch_forearm = col_double(),
## .. stddev_pitch_forearm = col_double(),
## .. var_pitch_forearm = col_double(),
## .. avg_yaw_forearm = col_double(),
## .. stddev_yaw_forearm = col_double(),
## .. var_yaw_forearm = col_double(),
## .. gyros_forearm_x = col_double(),
## .. gyros_forearm_y = col_double(),
## .. gyros_forearm_z = col_double(),
## .. accel_forearm_x = col_double(),
## .. accel_forearm_y = col_double(),
## .. accel_forearm_z = col_double(),
## .. magnet_forearm_x = col_double(),
## .. magnet_forearm_y = col_double(),
## .. magnet_forearm_z = col_double(),
## .. classe = col_character()
## .. )
Valores de la variable target
unique(df$classe)
## [1] "A" "B" "C" "D" "E"
Estudiamos los estadísticos básicos
summary(df)
## user_name raw_timestamp_part_1 raw_timestamp_part_2
## Length:19622 Min. :1.322e+09 Min. : 294
## Class :character 1st Qu.:1.323e+09 1st Qu.:252912
## Mode :character Median :1.323e+09 Median :496380
## Mean :1.323e+09 Mean :500656
## 3rd Qu.:1.323e+09 3rd Qu.:751891
## Max. :1.323e+09 Max. :998801
##
## cvtd_timestamp roll_belt pitch_belt yaw_belt
## Length:19622 Min. :-28.90 Min. :-55.8000 Min. :-180.00
## Class :character 1st Qu.: 1.10 1st Qu.: 1.7600 1st Qu.: -88.30
## Mode :character Median :113.00 Median : 5.2800 Median : -13.00
## Mean : 64.41 Mean : 0.3053 Mean : -11.21
## 3rd Qu.:123.00 3rd Qu.: 14.9000 3rd Qu.: 12.90
## Max. :162.00 Max. : 60.3000 Max. : 179.00
##
## total_accel_belt kurtosis_roll_belt kurtosis_picth_belt kurtosis_yaw_belt
## Min. : 0.00 Min. :-2.121 Min. :-2.190 Mode:logical
## 1st Qu.: 3.00 1st Qu.:-1.329 1st Qu.:-1.107 NA's:19622
## Median :17.00 Median :-0.899 Median :-0.151
## Mean :11.31 Mean :-0.220 Mean : 4.334
## 3rd Qu.:18.00 3rd Qu.:-0.219 3rd Qu.: 3.178
## Max. :29.00 Max. :33.000 Max. :58.000
## NA's :19226 NA's :19248
## skewness_roll_belt skewness_roll_belt.1 skewness_yaw_belt max_roll_belt
## Min. :-5.745 Min. :-7.616 Mode:logical Min. :-94.300
## 1st Qu.:-0.444 1st Qu.:-1.114 NA's:19622 1st Qu.:-88.000
## Median : 0.000 Median :-0.068 Median : -5.100
## Mean :-0.026 Mean :-0.296 Mean : -6.667
## 3rd Qu.: 0.417 3rd Qu.: 0.661 3rd Qu.: 18.500
## Max. : 3.595 Max. : 7.348 Max. :180.000
## NA's :19225 NA's :19248 NA's :19216
## max_picth_belt max_yaw_belt min_roll_belt min_pitch_belt
## Min. : 3.00 Min. :-2.10 Min. :-180.00 Min. : 0.00
## 1st Qu.: 5.00 1st Qu.:-1.30 1st Qu.: -88.40 1st Qu.: 3.00
## Median :18.00 Median :-0.90 Median : -7.85 Median :16.00
## Mean :12.92 Mean :-0.22 Mean : -10.44 Mean :10.76
## 3rd Qu.:19.00 3rd Qu.:-0.20 3rd Qu.: 9.05 3rd Qu.:17.00
## Max. :30.00 Max. :33.00 Max. : 173.00 Max. :23.00
## NA's :19216 NA's :19226 NA's :19216 NA's :19216
## min_yaw_belt amplitude_roll_belt amplitude_pitch_belt amplitude_yaw_belt
## Min. :-2.10 Min. : 0.000 Min. : 0.000 Min. :0
## 1st Qu.:-1.30 1st Qu.: 0.300 1st Qu.: 1.000 1st Qu.:0
## Median :-0.90 Median : 1.000 Median : 1.000 Median :0
## Mean :-0.22 Mean : 3.769 Mean : 2.167 Mean :0
## 3rd Qu.:-0.20 3rd Qu.: 2.083 3rd Qu.: 2.000 3rd Qu.:0
## Max. :33.00 Max. :360.000 Max. :12.000 Max. :0
## NA's :19226 NA's :19216 NA's :19216 NA's :19226
## var_total_accel_belt avg_roll_belt stddev_roll_belt var_roll_belt
## Min. : 0.000 Min. :-27.40 Min. : 0.000 Min. : 0.000
## 1st Qu.: 0.100 1st Qu.: 1.10 1st Qu.: 0.200 1st Qu.: 0.000
## Median : 0.200 Median :116.35 Median : 0.400 Median : 0.100
## Mean : 0.926 Mean : 68.06 Mean : 1.337 Mean : 7.699
## 3rd Qu.: 0.300 3rd Qu.:123.38 3rd Qu.: 0.700 3rd Qu.: 0.500
## Max. :16.500 Max. :157.40 Max. :14.200 Max. :200.700
## NA's :19216 NA's :19216 NA's :19216 NA's :19216
## avg_pitch_belt stddev_pitch_belt var_pitch_belt avg_yaw_belt
## Min. :-51.400 Min. :0.000 Min. : 0.000 Min. :-138.300
## 1st Qu.: 2.025 1st Qu.:0.200 1st Qu.: 0.000 1st Qu.: -88.175
## Median : 5.200 Median :0.400 Median : 0.100 Median : -6.550
## Mean : 0.520 Mean :0.603 Mean : 0.766 Mean : -8.831
## 3rd Qu.: 15.775 3rd Qu.:0.700 3rd Qu.: 0.500 3rd Qu.: 14.125
## Max. : 59.700 Max. :4.000 Max. :16.200 Max. : 173.500
## NA's :19216 NA's :19216 NA's :19216 NA's :19216
## stddev_yaw_belt var_yaw_belt gyros_belt_x gyros_belt_y
## Min. : 0.000 Min. : 0.000 Min. :-1.040000 Min. :-0.64000
## 1st Qu.: 0.100 1st Qu.: 0.010 1st Qu.:-0.030000 1st Qu.: 0.00000
## Median : 0.300 Median : 0.090 Median : 0.030000 Median : 0.02000
## Mean : 1.341 Mean : 107.487 Mean :-0.005592 Mean : 0.03959
## 3rd Qu.: 0.700 3rd Qu.: 0.475 3rd Qu.: 0.110000 3rd Qu.: 0.11000
## Max. :176.600 Max. :31183.240 Max. : 2.220000 Max. : 0.64000
## NA's :19216 NA's :19216
## gyros_belt_z accel_belt_x accel_belt_y accel_belt_z
## Min. :-1.4600 Min. :-120.000 Min. :-69.00 Min. :-275.00
## 1st Qu.:-0.2000 1st Qu.: -21.000 1st Qu.: 3.00 1st Qu.:-162.00
## Median :-0.1000 Median : -15.000 Median : 35.00 Median :-152.00
## Mean :-0.1305 Mean : -5.595 Mean : 30.15 Mean : -72.59
## 3rd Qu.:-0.0200 3rd Qu.: -5.000 3rd Qu.: 61.00 3rd Qu.: 27.00
## Max. : 1.6200 Max. : 85.000 Max. :164.00 Max. : 105.00
##
## magnet_belt_x magnet_belt_y magnet_belt_z roll_arm
## Min. :-52.0 Min. :354.0 Min. :-623.0 Min. :-180.00
## 1st Qu.: 9.0 1st Qu.:581.0 1st Qu.:-375.0 1st Qu.: -31.77
## Median : 35.0 Median :601.0 Median :-320.0 Median : 0.00
## Mean : 55.6 Mean :593.7 Mean :-345.5 Mean : 17.83
## 3rd Qu.: 59.0 3rd Qu.:610.0 3rd Qu.:-306.0 3rd Qu.: 77.30
## Max. :485.0 Max. :673.0 Max. : 293.0 Max. : 180.00
##
## pitch_arm yaw_arm total_accel_arm var_accel_arm
## Min. :-88.800 Min. :-180.0000 Min. : 1.00 Min. : 0.00
## 1st Qu.:-25.900 1st Qu.: -43.1000 1st Qu.:17.00 1st Qu.: 9.03
## Median : 0.000 Median : 0.0000 Median :27.00 Median : 40.61
## Mean : -4.612 Mean : -0.6188 Mean :25.51 Mean : 53.23
## 3rd Qu.: 11.200 3rd Qu.: 45.8750 3rd Qu.:33.00 3rd Qu.: 75.62
## Max. : 88.500 Max. : 180.0000 Max. :66.00 Max. :331.70
## NA's :19216
## avg_roll_arm stddev_roll_arm var_roll_arm avg_pitch_arm
## Min. :-166.67 Min. : 0.000 Min. : 0.000 Min. :-81.773
## 1st Qu.: -38.37 1st Qu.: 1.376 1st Qu.: 1.898 1st Qu.:-22.770
## Median : 0.00 Median : 5.702 Median : 32.517 Median : 0.000
## Mean : 12.68 Mean : 11.201 Mean : 417.264 Mean : -4.901
## 3rd Qu.: 76.33 3rd Qu.: 14.921 3rd Qu.: 222.647 3rd Qu.: 8.277
## Max. : 163.33 Max. :161.964 Max. :26232.208 Max. : 75.659
## NA's :19216 NA's :19216 NA's :19216 NA's :19216
## stddev_pitch_arm var_pitch_arm avg_yaw_arm stddev_yaw_arm
## Min. : 0.000 Min. : 0.000 Min. :-173.440 Min. : 0.000
## 1st Qu.: 1.642 1st Qu.: 2.697 1st Qu.: -29.198 1st Qu.: 2.577
## Median : 8.133 Median : 66.146 Median : 0.000 Median : 16.682
## Mean :10.383 Mean : 195.864 Mean : 2.359 Mean : 22.270
## 3rd Qu.:16.327 3rd Qu.: 266.576 3rd Qu.: 38.185 3rd Qu.: 35.984
## Max. :43.412 Max. :1884.565 Max. : 152.000 Max. :177.044
## NA's :19216 NA's :19216 NA's :19216 NA's :19216
## var_yaw_arm gyros_arm_x gyros_arm_y gyros_arm_z
## Min. : 0.000 Min. :-6.37000 Min. :-3.4400 Min. :-2.3300
## 1st Qu.: 6.642 1st Qu.:-1.33000 1st Qu.:-0.8000 1st Qu.:-0.0700
## Median : 278.309 Median : 0.08000 Median :-0.2400 Median : 0.2300
## Mean : 1055.933 Mean : 0.04277 Mean :-0.2571 Mean : 0.2695
## 3rd Qu.: 1294.850 3rd Qu.: 1.57000 3rd Qu.: 0.1400 3rd Qu.: 0.7200
## Max. :31344.568 Max. : 4.87000 Max. : 2.8400 Max. : 3.0200
## NA's :19216
## accel_arm_x accel_arm_y accel_arm_z magnet_arm_x
## Min. :-404.00 Min. :-318.0 Min. :-636.00 Min. :-584.0
## 1st Qu.:-242.00 1st Qu.: -54.0 1st Qu.:-143.00 1st Qu.:-300.0
## Median : -44.00 Median : 14.0 Median : -47.00 Median : 289.0
## Mean : -60.24 Mean : 32.6 Mean : -71.25 Mean : 191.7
## 3rd Qu.: 84.00 3rd Qu.: 139.0 3rd Qu.: 23.00 3rd Qu.: 637.0
## Max. : 437.00 Max. : 308.0 Max. : 292.00 Max. : 782.0
##
## magnet_arm_y magnet_arm_z kurtosis_roll_arm kurtosis_picth_arm
## Min. :-392.0 Min. :-597.0 Min. :-1.809 Min. :-2.084
## 1st Qu.: -9.0 1st Qu.: 131.2 1st Qu.:-1.345 1st Qu.:-1.280
## Median : 202.0 Median : 444.0 Median :-0.894 Median :-1.010
## Mean : 156.6 Mean : 306.5 Mean :-0.366 Mean :-0.542
## 3rd Qu.: 323.0 3rd Qu.: 545.0 3rd Qu.:-0.038 3rd Qu.:-0.379
## Max. : 583.0 Max. : 694.0 Max. :21.456 Max. :19.751
## NA's :19294 NA's :19296
## kurtosis_yaw_arm skewness_roll_arm skewness_pitch_arm skewness_yaw_arm
## Min. :-2.103 Min. :-2.541 Min. :-4.565 Min. :-6.708
## 1st Qu.:-1.220 1st Qu.:-0.561 1st Qu.:-0.618 1st Qu.:-0.743
## Median :-0.733 Median : 0.040 Median :-0.035 Median :-0.133
## Mean : 0.406 Mean : 0.068 Mean :-0.065 Mean :-0.229
## 3rd Qu.: 0.115 3rd Qu.: 0.671 3rd Qu.: 0.454 3rd Qu.: 0.344
## Max. :56.000 Max. : 4.394 Max. : 3.043 Max. : 7.483
## NA's :19227 NA's :19293 NA's :19296 NA's :19227
## max_roll_arm max_picth_arm max_yaw_arm min_roll_arm
## Min. :-73.100 Min. :-173.000 Min. : 4.00 Min. :-89.10
## 1st Qu.: -0.175 1st Qu.: -1.975 1st Qu.:29.00 1st Qu.:-41.98
## Median : 4.950 Median : 23.250 Median :34.00 Median :-22.45
## Mean : 11.236 Mean : 35.751 Mean :35.46 Mean :-21.22
## 3rd Qu.: 26.775 3rd Qu.: 95.975 3rd Qu.:41.00 3rd Qu.: 0.00
## Max. : 85.500 Max. : 180.000 Max. :65.00 Max. : 66.40
## NA's :19216 NA's :19216 NA's :19216 NA's :19216
## min_pitch_arm min_yaw_arm amplitude_roll_arm amplitude_pitch_arm
## Min. :-180.00 Min. : 1.00 Min. : 0.000 Min. : 0.000
## 1st Qu.: -72.62 1st Qu.: 8.00 1st Qu.: 5.425 1st Qu.: 9.925
## Median : -33.85 Median :13.00 Median : 28.450 Median : 54.900
## Mean : -33.92 Mean :14.66 Mean : 32.452 Mean : 69.677
## 3rd Qu.: 0.00 3rd Qu.:19.00 3rd Qu.: 50.960 3rd Qu.:115.175
## Max. : 152.00 Max. :38.00 Max. :119.500 Max. :360.000
## NA's :19216 NA's :19216 NA's :19216 NA's :19216
## amplitude_yaw_arm roll_dumbbell pitch_dumbbell yaw_dumbbell
## Min. : 0.00 Min. :-153.71 Min. :-149.59 Min. :-150.871
## 1st Qu.:13.00 1st Qu.: -18.49 1st Qu.: -40.89 1st Qu.: -77.644
## Median :22.00 Median : 48.17 Median : -20.96 Median : -3.324
## Mean :20.79 Mean : 23.84 Mean : -10.78 Mean : 1.674
## 3rd Qu.:28.75 3rd Qu.: 67.61 3rd Qu.: 17.50 3rd Qu.: 79.643
## Max. :52.00 Max. : 153.55 Max. : 149.40 Max. : 154.952
## NA's :19216
## kurtosis_roll_dumbbell kurtosis_picth_dumbbell kurtosis_yaw_dumbbell
## Min. :-2.174 Min. :-2.200 Mode:logical
## 1st Qu.:-0.682 1st Qu.:-0.721 NA's:19622
## Median :-0.033 Median :-0.133
## Mean : 0.452 Mean : 0.286
## 3rd Qu.: 0.940 3rd Qu.: 0.584
## Max. :54.998 Max. :55.628
## NA's :19221 NA's :19218
## skewness_roll_dumbbell skewness_pitch_dumbbell skewness_yaw_dumbbell
## Min. :-7.384 Min. :-7.447 Mode:logical
## 1st Qu.:-0.581 1st Qu.:-0.526 NA's:19622
## Median :-0.076 Median :-0.091
## Mean :-0.115 Mean :-0.035
## 3rd Qu.: 0.400 3rd Qu.: 0.505
## Max. : 1.958 Max. : 3.769
## NA's :19220 NA's :19217
## max_roll_dumbbell max_picth_dumbbell max_yaw_dumbbell min_roll_dumbbell
## Min. :-70.10 Min. :-112.90 Min. :-2.20 Min. :-149.60
## 1st Qu.:-27.15 1st Qu.: -66.70 1st Qu.:-0.70 1st Qu.: -59.67
## Median : 14.85 Median : 40.05 Median : 0.00 Median : -43.55
## Mean : 13.76 Mean : 32.75 Mean : 0.45 Mean : -41.24
## 3rd Qu.: 50.58 3rd Qu.: 133.22 3rd Qu.: 0.90 3rd Qu.: -25.20
## Max. :137.00 Max. : 155.00 Max. :55.00 Max. : 73.20
## NA's :19216 NA's :19216 NA's :19221 NA's :19216
## min_pitch_dumbbell min_yaw_dumbbell amplitude_roll_dumbbell
## Min. :-147.00 Min. :-2.20 Min. : 0.00
## 1st Qu.: -91.80 1st Qu.:-0.70 1st Qu.: 14.97
## Median : -66.15 Median : 0.00 Median : 35.05
## Mean : -33.18 Mean : 0.45 Mean : 55.00
## 3rd Qu.: 21.20 3rd Qu.: 0.90 3rd Qu.: 81.04
## Max. : 120.90 Max. :55.00 Max. :256.48
## NA's :19216 NA's :19221 NA's :19216
## amplitude_pitch_dumbbell amplitude_yaw_dumbbell total_accel_dumbbell
## Min. : 0.00 Min. :0 Min. : 0.00
## 1st Qu.: 17.06 1st Qu.:0 1st Qu.: 4.00
## Median : 41.73 Median :0 Median :10.00
## Mean : 65.93 Mean :0 Mean :13.72
## 3rd Qu.: 99.55 3rd Qu.:0 3rd Qu.:19.00
## Max. :273.59 Max. :0 Max. :58.00
## NA's :19216 NA's :19221
## var_accel_dumbbell avg_roll_dumbbell stddev_roll_dumbbell var_roll_dumbbell
## Min. : 0.000 Min. :-128.96 Min. : 0.000 Min. : 0.00
## 1st Qu.: 0.378 1st Qu.: -12.33 1st Qu.: 4.639 1st Qu.: 21.52
## Median : 1.000 Median : 48.23 Median : 12.204 Median : 148.95
## Mean : 4.388 Mean : 23.86 Mean : 20.761 Mean : 1020.27
## 3rd Qu.: 3.434 3rd Qu.: 64.37 3rd Qu.: 26.356 3rd Qu.: 694.65
## Max. :230.428 Max. : 125.99 Max. :123.778 Max. :15321.01
## NA's :19216 NA's :19216 NA's :19216 NA's :19216
## avg_pitch_dumbbell stddev_pitch_dumbbell var_pitch_dumbbell avg_yaw_dumbbell
## Min. :-70.73 Min. : 0.000 Min. : 0.00 Min. :-117.950
## 1st Qu.:-42.00 1st Qu.: 3.482 1st Qu.: 12.12 1st Qu.: -76.696
## Median :-19.91 Median : 8.089 Median : 65.44 Median : -4.505
## Mean :-12.33 Mean :13.147 Mean : 350.31 Mean : 0.202
## 3rd Qu.: 13.21 3rd Qu.:19.238 3rd Qu.: 370.11 3rd Qu.: 71.234
## Max. : 94.28 Max. :82.680 Max. :6836.02 Max. : 134.905
## NA's :19216 NA's :19216 NA's :19216 NA's :19216
## stddev_yaw_dumbbell var_yaw_dumbbell gyros_dumbbell_x gyros_dumbbell_y
## Min. : 0.000 Min. : 0.00 Min. :-204.0000 Min. :-2.10000
## 1st Qu.: 3.885 1st Qu.: 15.09 1st Qu.: -0.0300 1st Qu.:-0.14000
## Median : 10.264 Median : 105.35 Median : 0.1300 Median : 0.03000
## Mean : 16.647 Mean : 589.84 Mean : 0.1611 Mean : 0.04606
## 3rd Qu.: 24.674 3rd Qu.: 608.79 3rd Qu.: 0.3500 3rd Qu.: 0.21000
## Max. :107.088 Max. :11467.91 Max. : 2.2200 Max. :52.00000
## NA's :19216 NA's :19216
## gyros_dumbbell_z accel_dumbbell_x accel_dumbbell_y accel_dumbbell_z
## Min. : -2.380 Min. :-419.00 Min. :-189.00 Min. :-334.00
## 1st Qu.: -0.310 1st Qu.: -50.00 1st Qu.: -8.00 1st Qu.:-142.00
## Median : -0.130 Median : -8.00 Median : 41.50 Median : -1.00
## Mean : -0.129 Mean : -28.62 Mean : 52.63 Mean : -38.32
## 3rd Qu.: 0.030 3rd Qu.: 11.00 3rd Qu.: 111.00 3rd Qu.: 38.00
## Max. :317.000 Max. : 235.00 Max. : 315.00 Max. : 318.00
##
## magnet_dumbbell_x magnet_dumbbell_y magnet_dumbbell_z roll_forearm
## Min. :-643.0 Min. :-3600 Min. :-262.00 Min. :-180.0000
## 1st Qu.:-535.0 1st Qu.: 231 1st Qu.: -45.00 1st Qu.: -0.7375
## Median :-479.0 Median : 311 Median : 13.00 Median : 21.7000
## Mean :-328.5 Mean : 221 Mean : 46.05 Mean : 33.8265
## 3rd Qu.:-304.0 3rd Qu.: 390 3rd Qu.: 95.00 3rd Qu.: 140.0000
## Max. : 592.0 Max. : 633 Max. : 452.00 Max. : 180.0000
##
## pitch_forearm yaw_forearm kurtosis_roll_forearm
## Min. :-72.50 Min. :-180.00 Min. :-1.879
## 1st Qu.: 0.00 1st Qu.: -68.60 1st Qu.:-1.398
## Median : 9.24 Median : 0.00 Median :-1.119
## Mean : 10.71 Mean : 19.21 Mean :-0.689
## 3rd Qu.: 28.40 3rd Qu.: 110.00 3rd Qu.:-0.618
## Max. : 89.80 Max. : 180.00 Max. :40.060
## NA's :19300
## kurtosis_picth_forearm kurtosis_yaw_forearm skewness_roll_forearm
## Min. :-2.098 Mode:logical Min. :-2.297
## 1st Qu.:-1.376 NA's:19622 1st Qu.:-0.402
## Median :-0.890 Median : 0.003
## Mean : 0.419 Mean :-0.009
## 3rd Qu.: 0.054 3rd Qu.: 0.370
## Max. :33.626 Max. : 5.856
## NA's :19301 NA's :19299
## skewness_pitch_forearm skewness_yaw_forearm max_roll_forearm max_picth_forearm
## Min. :-5.241 Mode:logical Min. :-66.60 Min. :-151.00
## 1st Qu.:-0.881 NA's:19622 1st Qu.: 0.00 1st Qu.: 0.00
## Median :-0.156 Median : 26.80 Median : 113.00
## Mean :-0.223 Mean : 24.49 Mean : 81.49
## 3rd Qu.: 0.514 3rd Qu.: 45.95 3rd Qu.: 174.75
## Max. : 4.464 Max. : 89.80 Max. : 180.00
## NA's :19301 NA's :19216 NA's :19216
## max_yaw_forearm min_roll_forearm min_pitch_forearm min_yaw_forearm
## Min. :-1.900 Min. :-72.500 Min. :-180.00 Min. :-1.900
## 1st Qu.:-1.400 1st Qu.: -6.075 1st Qu.:-175.00 1st Qu.:-1.400
## Median :-1.100 Median : 0.000 Median : -61.00 Median :-1.100
## Mean :-0.689 Mean : -0.167 Mean : -57.57 Mean :-0.689
## 3rd Qu.:-0.600 3rd Qu.: 12.075 3rd Qu.: 0.00 3rd Qu.:-0.600
## Max. :40.100 Max. : 62.100 Max. : 167.00 Max. :40.100
## NA's :19300 NA's :19216 NA's :19216 NA's :19300
## amplitude_roll_forearm amplitude_pitch_forearm amplitude_yaw_forearm
## Min. : 0.000 Min. : 0.0 Min. :0
## 1st Qu.: 1.125 1st Qu.: 2.0 1st Qu.:0
## Median : 17.770 Median : 83.7 Median :0
## Mean : 24.653 Mean :139.1 Mean :0
## 3rd Qu.: 39.875 3rd Qu.:350.0 3rd Qu.:0
## Max. :126.000 Max. :360.0 Max. :0
## NA's :19216 NA's :19216 NA's :19300
## total_accel_forearm var_accel_forearm avg_roll_forearm stddev_roll_forearm
## Min. : 0.00 Min. : 0.000 Min. :-177.234 Min. : 0.000
## 1st Qu.: 29.00 1st Qu.: 6.759 1st Qu.: -0.909 1st Qu.: 0.428
## Median : 36.00 Median : 21.165 Median : 11.172 Median : 8.030
## Mean : 34.72 Mean : 33.502 Mean : 33.165 Mean : 41.986
## 3rd Qu.: 41.00 3rd Qu.: 51.240 3rd Qu.: 107.132 3rd Qu.: 85.373
## Max. :108.00 Max. :172.606 Max. : 177.256 Max. :179.171
## NA's :19216 NA's :19216 NA's :19216
## var_roll_forearm avg_pitch_forearm stddev_pitch_forearm var_pitch_forearm
## Min. : 0.00 Min. :-68.17 Min. : 0.000 Min. : 0.000
## 1st Qu.: 0.18 1st Qu.: 0.00 1st Qu.: 0.336 1st Qu.: 0.113
## Median : 64.48 Median : 12.02 Median : 5.516 Median : 30.425
## Mean : 5274.10 Mean : 11.79 Mean : 7.977 Mean : 139.593
## 3rd Qu.: 7289.08 3rd Qu.: 28.48 3rd Qu.:12.866 3rd Qu.: 165.532
## Max. :32102.24 Max. : 72.09 Max. :47.745 Max. :2279.617
## NA's :19216 NA's :19216 NA's :19216 NA's :19216
## avg_yaw_forearm stddev_yaw_forearm var_yaw_forearm gyros_forearm_x
## Min. :-155.06 Min. : 0.000 Min. : 0.00 Min. :-22.000
## 1st Qu.: -26.26 1st Qu.: 0.524 1st Qu.: 0.27 1st Qu.: -0.220
## Median : 0.00 Median : 24.743 Median : 612.21 Median : 0.050
## Mean : 18.00 Mean : 44.854 Mean : 4639.85 Mean : 0.158
## 3rd Qu.: 85.79 3rd Qu.: 85.817 3rd Qu.: 7368.41 3rd Qu.: 0.560
## Max. : 169.24 Max. :197.508 Max. :39009.33 Max. : 3.970
## NA's :19216 NA's :19216 NA's :19216
## gyros_forearm_y gyros_forearm_z accel_forearm_x accel_forearm_y
## Min. : -7.02000 Min. : -8.0900 Min. :-498.00 Min. :-632.0
## 1st Qu.: -1.46000 1st Qu.: -0.1800 1st Qu.:-178.00 1st Qu.: 57.0
## Median : 0.03000 Median : 0.0800 Median : -57.00 Median : 201.0
## Mean : 0.07517 Mean : 0.1512 Mean : -61.65 Mean : 163.7
## 3rd Qu.: 1.62000 3rd Qu.: 0.4900 3rd Qu.: 76.00 3rd Qu.: 312.0
## Max. :311.00000 Max. :231.0000 Max. : 477.00 Max. : 923.0
##
## accel_forearm_z magnet_forearm_x magnet_forearm_y magnet_forearm_z
## Min. :-446.00 Min. :-1280.0 Min. :-896.0 Min. :-973.0
## 1st Qu.:-182.00 1st Qu.: -616.0 1st Qu.: 2.0 1st Qu.: 191.0
## Median : -39.00 Median : -378.0 Median : 591.0 Median : 511.0
## Mean : -55.29 Mean : -312.6 Mean : 380.1 Mean : 393.6
## 3rd Qu.: 26.00 3rd Qu.: -73.0 3rd Qu.: 737.0 3rd Qu.: 653.0
## Max. : 291.00 Max. : 672.0 Max. :1480.0 Max. :1090.0
##
## classe
## Length:19622
## Class :character
## Mode :character
##
##
##
##
Observamos algunos problemas:
Trataremos estos problemas más adelante
Observamos algunos problemas:
df$user_name <- NULL
dim(df)
## [1] 19622 156
Hemos detectado que los datos tienen columnas con demasiados nulos. Vamos a tratar esos casos.
colSums(is.na.data.frame(df))
## raw_timestamp_part_1 raw_timestamp_part_2 cvtd_timestamp
## 0 0 0
## roll_belt pitch_belt yaw_belt
## 0 0 0
## total_accel_belt kurtosis_roll_belt kurtosis_picth_belt
## 0 19226 19248
## kurtosis_yaw_belt skewness_roll_belt skewness_roll_belt.1
## 19622 19225 19248
## skewness_yaw_belt max_roll_belt max_picth_belt
## 19622 19216 19216
## max_yaw_belt min_roll_belt min_pitch_belt
## 19226 19216 19216
## min_yaw_belt amplitude_roll_belt amplitude_pitch_belt
## 19226 19216 19216
## amplitude_yaw_belt var_total_accel_belt avg_roll_belt
## 19226 19216 19216
## stddev_roll_belt var_roll_belt avg_pitch_belt
## 19216 19216 19216
## stddev_pitch_belt var_pitch_belt avg_yaw_belt
## 19216 19216 19216
## stddev_yaw_belt var_yaw_belt gyros_belt_x
## 19216 19216 0
## gyros_belt_y gyros_belt_z accel_belt_x
## 0 0 0
## accel_belt_y accel_belt_z magnet_belt_x
## 0 0 0
## magnet_belt_y magnet_belt_z roll_arm
## 0 0 0
## pitch_arm yaw_arm total_accel_arm
## 0 0 0
## var_accel_arm avg_roll_arm stddev_roll_arm
## 19216 19216 19216
## var_roll_arm avg_pitch_arm stddev_pitch_arm
## 19216 19216 19216
## var_pitch_arm avg_yaw_arm stddev_yaw_arm
## 19216 19216 19216
## var_yaw_arm gyros_arm_x gyros_arm_y
## 19216 0 0
## gyros_arm_z accel_arm_x accel_arm_y
## 0 0 0
## accel_arm_z magnet_arm_x magnet_arm_y
## 0 0 0
## magnet_arm_z kurtosis_roll_arm kurtosis_picth_arm
## 0 19294 19296
## kurtosis_yaw_arm skewness_roll_arm skewness_pitch_arm
## 19227 19293 19296
## skewness_yaw_arm max_roll_arm max_picth_arm
## 19227 19216 19216
## max_yaw_arm min_roll_arm min_pitch_arm
## 19216 19216 19216
## min_yaw_arm amplitude_roll_arm amplitude_pitch_arm
## 19216 19216 19216
## amplitude_yaw_arm roll_dumbbell pitch_dumbbell
## 19216 0 0
## yaw_dumbbell kurtosis_roll_dumbbell kurtosis_picth_dumbbell
## 0 19221 19218
## kurtosis_yaw_dumbbell skewness_roll_dumbbell skewness_pitch_dumbbell
## 19622 19220 19217
## skewness_yaw_dumbbell max_roll_dumbbell max_picth_dumbbell
## 19622 19216 19216
## max_yaw_dumbbell min_roll_dumbbell min_pitch_dumbbell
## 19221 19216 19216
## min_yaw_dumbbell amplitude_roll_dumbbell amplitude_pitch_dumbbell
## 19221 19216 19216
## amplitude_yaw_dumbbell total_accel_dumbbell var_accel_dumbbell
## 19221 0 19216
## avg_roll_dumbbell stddev_roll_dumbbell var_roll_dumbbell
## 19216 19216 19216
## avg_pitch_dumbbell stddev_pitch_dumbbell var_pitch_dumbbell
## 19216 19216 19216
## avg_yaw_dumbbell stddev_yaw_dumbbell var_yaw_dumbbell
## 19216 19216 19216
## gyros_dumbbell_x gyros_dumbbell_y gyros_dumbbell_z
## 0 0 0
## accel_dumbbell_x accel_dumbbell_y accel_dumbbell_z
## 0 0 0
## magnet_dumbbell_x magnet_dumbbell_y magnet_dumbbell_z
## 0 0 0
## roll_forearm pitch_forearm yaw_forearm
## 0 0 0
## kurtosis_roll_forearm kurtosis_picth_forearm kurtosis_yaw_forearm
## 19300 19301 19622
## skewness_roll_forearm skewness_pitch_forearm skewness_yaw_forearm
## 19299 19301 19622
## max_roll_forearm max_picth_forearm max_yaw_forearm
## 19216 19216 19300
## min_roll_forearm min_pitch_forearm min_yaw_forearm
## 19216 19216 19300
## amplitude_roll_forearm amplitude_pitch_forearm amplitude_yaw_forearm
## 19216 19216 19300
## total_accel_forearm var_accel_forearm avg_roll_forearm
## 0 19216 19216
## stddev_roll_forearm var_roll_forearm avg_pitch_forearm
## 19216 19216 19216
## stddev_pitch_forearm var_pitch_forearm avg_yaw_forearm
## 19216 19216 19216
## stddev_yaw_forearm var_yaw_forearm gyros_forearm_x
## 19216 19216 0
## gyros_forearm_y gyros_forearm_z accel_forearm_x
## 0 0 0
## accel_forearm_y accel_forearm_z magnet_forearm_x
## 0 0 0
## magnet_forearm_y magnet_forearm_z classe
## 0 0 0
Las 100 columnas identificadas contienen demasiados nulos. Las eliminamos.
cols_var_nulo <- colnames(df)[colSums(is.na(df)) > 0]
df <- df[, !colnames(df) %in% cols_var_nulo]
dim(df)
## [1] 19622 56
No existen variables duplicadas
sum(duplicated(t(df)))
## [1] 0
No existen registros duplicados
sum(duplicated(df))
## [1] 0
No existen campos que tengan siempre un mismo valor.
sum(
sapply(df, function(x) length(unique(x)) == 1)
)
## [1] 0
Analicemos las variables numéricas. Para ello utilizamos histogramas y boxplots.
varNumericas <- names(df[sapply(df, class) == "numeric"])
par(mfrow=c(5,2), mar = c(2,0,2,2))
for (var in varNumericas){
boxplot(df[[var]], horizontal=TRUE, outline=TRUE, col = "green3", main = var)
hist(df[[var]], main = var, col = "pink2")
}
## Warning in breaks[-1L] + breaks[-nB]: NAs producidos por enteros excedidos
En general, observamos distribuciones alejadas de la distribución normal: distribuciones multimodales (sobre todo bimodales y trimodales), distribuciones con largas colas, etc. Además, en algunas variables, observamos la presencia de valores atípicos. Esto puede afectar al rendimiento de algunos modelos, por lo que debemos tenerlo en cuenta.
Para las variables categóricas realizamos diagramas de barras.
varCategoricas <- names(df[sapply(df, class) == "character"])
for (var in varCategoricas){
counts <- table(df[,var])
density <- counts / sum(counts)
print(paste("Distribución: ", var))
print(density)
barplot(density, main = paste("Gráfico de barras de: ", var), horiz = FALSE, col="lightblue3")
}
## [1] "Distribución: cvtd_timestamp"
##
## 02/12/2011 13:32 02/12/2011 13:33 02/12/2011 13:34 02/12/2011 13:35
## 0.009020487 0.067322393 0.070074406 0.051931505
## 02/12/2011 14:56 02/12/2011 14:57 02/12/2011 14:58 02/12/2011 14:59
## 0.011976353 0.070329222 0.069513811 0.028386505
## 05/12/2011 11:23 05/12/2011 11:24 05/12/2011 11:25 05/12/2011 14:22
## 0.009683009 0.076291917 0.072622567 0.013607176
## 05/12/2011 14:23 05/12/2011 14:24 28/11/2011 14:13 28/11/2011 14:14
## 0.069819590 0.049587198 0.042452349 0.076342880
## 28/11/2011 14:15 30/11/2011 17:10 30/11/2011 17:11 30/11/2011 17:12
## 0.037661808 0.044287025 0.073387015 0.055702783
## [1] "Distribución: classe"
##
## A B C D E
## 0.2843747 0.1935073 0.1743961 0.1638977 0.1838243
Los datos reflejan cuatro fechas: dos a finales de Noviembre 2011, dos a principios de Diciembre 2011. La fecha exacta no es un buen predictor, por lo que más adelante trataremos este campo.
Las clases están aproximadamente balanceadas, no nos enfrentamos a un problema de clases fuertemente desbalanceadas.
Estudiamos la correlación entre las variables. Para poder incluir la variable dependiente, que es de tipo categórico, le aplicamos una transformación dummy.
class_unique_values <- levels(as.factor(df$classe))
class_dummies <- data.frame(model.matrix(~classe, data = df))[ ,2:length(class_unique_values)]
rm(class_unique_values) # eliminamos el objeto class_unique_values, ya no es necesario
head(class_dummies)
## classeB classeC classeD classeE
## 1 0 0 0 0
## 2 0 0 0 0
## 3 0 0 0 0
## 4 0 0 0 0
## 5 0 0 0 0
## 6 0 0 0 0
La incluímos en el dataframe, que renombramos como df_dm
df_dm <- df
df_dm$classe <- NULL
df_dm <- bind_cols(df_dm, class_dummies)
rm(class_dummies) # eliminamos el objeto class_dummies, ya no es necesario
tail(df_dm)
## # A tibble: 6 x 59
## raw_timestamp_p~ raw_timestamp_p~ cvtd_timestamp roll_belt pitch_belt yaw_belt
## <dbl> <dbl> <chr> <dbl> <dbl> <dbl>
## 1 1322832937 588324 02/12/2011 13~ 148 -34.7 129
## 2 1322832937 588376 02/12/2011 13~ 147 -34.8 129
## 3 1322832937 596287 02/12/2011 13~ 145 -35.3 130
## 4 1322832937 636283 02/12/2011 13~ 145 -35.5 130
## 5 1322832937 964299 02/12/2011 13~ 143 -35.9 131
## 6 1322832937 972293 02/12/2011 13~ 143 -36 132
## # ... with 53 more variables: total_accel_belt <dbl>, gyros_belt_x <dbl>,
## # gyros_belt_y <dbl>, gyros_belt_z <dbl>, accel_belt_x <dbl>,
## # accel_belt_y <dbl>, accel_belt_z <dbl>, magnet_belt_x <dbl>,
## # magnet_belt_y <dbl>, magnet_belt_z <dbl>, roll_arm <dbl>, pitch_arm <dbl>,
## # yaw_arm <dbl>, total_accel_arm <dbl>, gyros_arm_x <dbl>, gyros_arm_y <dbl>,
## # gyros_arm_z <dbl>, accel_arm_x <dbl>, accel_arm_y <dbl>, accel_arm_z <dbl>,
## # magnet_arm_x <dbl>, magnet_arm_y <dbl>, magnet_arm_z <dbl>,
## # roll_dumbbell <dbl>, pitch_dumbbell <dbl>, yaw_dumbbell <dbl>,
## # total_accel_dumbbell <dbl>, gyros_dumbbell_x <dbl>, gyros_dumbbell_y <dbl>,
## # gyros_dumbbell_z <dbl>, accel_dumbbell_x <dbl>, accel_dumbbell_y <dbl>,
## # accel_dumbbell_z <dbl>, magnet_dumbbell_x <dbl>, magnet_dumbbell_y <dbl>,
## # magnet_dumbbell_z <dbl>, roll_forearm <dbl>, pitch_forearm <dbl>,
## # yaw_forearm <dbl>, total_accel_forearm <dbl>, gyros_forearm_x <dbl>,
## # gyros_forearm_y <dbl>, gyros_forearm_z <dbl>, accel_forearm_x <dbl>,
## # accel_forearm_y <dbl>, accel_forearm_z <dbl>, magnet_forearm_x <dbl>,
## # magnet_forearm_y <dbl>, magnet_forearm_z <dbl>, classeB <dbl>,
## # classeC <dbl>, classeD <dbl>, classeE <dbl>
representamos la matriz de correlaciones
corrplot(
cor( df_dm[sapply(df_dm, class) == "numeric"] )
)
Observamos que, en general, las variables independientes están débilmente correladas con la variable dependiente. Por otro lado, algunas variables independientes están fuertemente correladas entre sí.
La variable de fecha hora cvtd_timestamp está codificada en tiempo UNIX en los campos raw_timestamp_part_1 (parte entera del timestamp) y raw_timestamp_part_2 (parte decimal del timestamp).
Además, la fecha precisa no es buen predictor. Una opción sería extaer información útil como la hora, día de la semana, día del mes o mes para detectar patrones relevantes. Sin embargo, en nuestro dataset existen solamente 4 días registrados, y en cada día el intervalo horario es muy reducido.
sort(
levels(as.factor(df$cvtd_timestamp))
)
## [1] "02/12/2011 13:32" "02/12/2011 13:33" "02/12/2011 13:34" "02/12/2011 13:35"
## [5] "02/12/2011 14:56" "02/12/2011 14:57" "02/12/2011 14:58" "02/12/2011 14:59"
## [9] "05/12/2011 11:23" "05/12/2011 11:24" "05/12/2011 11:25" "05/12/2011 14:22"
## [13] "05/12/2011 14:23" "05/12/2011 14:24" "28/11/2011 14:13" "28/11/2011 14:14"
## [17] "28/11/2011 14:15" "30/11/2011 17:10" "30/11/2011 17:11" "30/11/2011 17:12"
Por lo tanto, optamos por eliminar esta información:
cols_to_delete <- c("cvtd_timestamp", "raw_timestamp_part_1", "raw_timestamp_part_2")
df <- df[, !colnames(df) %in% cols_to_delete]
df_dm <- df_dm[, !colnames(df_dm) %in% cols_to_delete]
# alternativa:
# df <- df %>% select(-cvtd_timestamp,-raw_timestamp_part_1,-raw_timestamp_part_2)
dim(df)
## [1] 19622 53
dim(df_dm)
## [1] 19622 56
Eliminamos la etiqueta de datos para trabajar con un problema no supervisado. Normalizamos los datos.
df_norm <- data.Normalization( data.frame(df[, 1:52]), "n4") # n4 - unitization with zero minimum ((x-min)/range))
head(df_norm)
## roll_belt pitch_belt yaw_belt total_accel_belt gyros_belt_x gyros_belt_y
## 1 0.1587742 0.5501292 0.2384401 0.1034483 0.3190184 0.500000
## 2 0.1587742 0.5501292 0.2384401 0.1034483 0.3251534 0.500000
## 3 0.1588266 0.5501292 0.2384401 0.1034483 0.3190184 0.500000
## 4 0.1591409 0.5499569 0.2384401 0.1034483 0.3251534 0.500000
## 5 0.1591409 0.5501292 0.2384401 0.1034483 0.3251534 0.515625
## 6 0.1589838 0.5500431 0.2384401 0.1034483 0.3251534 0.500000
## gyros_belt_z accel_belt_x accel_belt_y accel_belt_z magnet_belt_x
## 1 0.4675325 0.4829268 0.3133047 0.7815789 0.09124767
## 2 0.4675325 0.4780488 0.3133047 0.7815789 0.08379888
## 3 0.4675325 0.4878049 0.3175966 0.7842105 0.09310987
## 4 0.4642857 0.4780488 0.3090129 0.7789474 0.08566108
## 5 0.4675325 0.4829268 0.3047210 0.7868421 0.08566108
## 6 0.4675325 0.4829268 0.3133047 0.7789474 0.09683426
## magnet_belt_y magnet_belt_z roll_arm pitch_arm yaw_arm total_accel_arm
## 1 0.7680251 0.3384279 0.1444444 0.6277496 0.05277778 0.5076923
## 2 0.7962382 0.3406114 0.1444444 0.6277496 0.05277778 0.5076923
## 3 0.7711599 0.3471616 0.1444444 0.6277496 0.05277778 0.5076923
## 4 0.7836991 0.3417031 0.1444444 0.6254935 0.05277778 0.5076923
## 5 0.7711599 0.3504367 0.1444444 0.6254935 0.05277778 0.5076923
## 6 0.7805643 0.3395197 0.1444444 0.6249295 0.05277778 0.5076923
## gyros_arm_x gyros_arm_y gyros_arm_z accel_arm_x accel_arm_y accel_arm_z
## 1 0.5667260 0.5477707 0.4317757 0.1379310 0.6821086 0.5528017
## 2 0.5685053 0.5445860 0.4317757 0.1355529 0.6837061 0.5506466
## 3 0.5685053 0.5445860 0.4317757 0.1367420 0.6837061 0.5495690
## 4 0.5685053 0.5429936 0.4392523 0.1367420 0.6853035 0.5528017
## 5 0.5667260 0.5429936 0.4355140 0.1367420 0.6853035 0.5528017
## 6 0.5685053 0.5429936 0.4355140 0.1367420 0.6853035 0.5538793
## magnet_arm_x magnet_arm_y magnet_arm_z roll_dumbbell pitch_dumbbell
## 1 0.1581259 0.7476923 0.8621224 0.5427530 0.2645508
## 2 0.1573939 0.7476923 0.8597986 0.5430087 0.2640708
## 3 0.1581259 0.7548718 0.8597986 0.5420974 0.2652728
## 4 0.1551977 0.7548718 0.8590240 0.5439866 0.2648859
## 5 0.1537335 0.7476923 0.8543765 0.5438157 0.2647696
## 6 0.1573939 0.7528205 0.8597986 0.5438279 0.2634685
## yaw_dumbbell total_accel_dumbbell gyros_dumbbell_x gyros_dumbbell_y
## 1 0.2158017 0.637931 0.9892348 0.03844732
## 2 0.2163356 0.637931 0.9892348 0.03844732
## 3 0.2149291 0.637931 0.9892348 0.03844732
## 4 0.2158027 0.637931 0.9892348 0.03844732
## 5 0.2158700 0.637931 0.9892348 0.03844732
## 6 0.2171388 0.637931 0.9892348 0.03844732
## gyros_dumbbell_z accel_dumbbell_x accel_dumbbell_y accel_dumbbell_z
## 1 0.007451938 0.2828746 0.4682540 0.09662577
## 2 0.007451938 0.2844037 0.4682540 0.09969325
## 3 0.007451938 0.2859327 0.4662698 0.09815951
## 4 0.007389317 0.2859327 0.4702381 0.09969325
## 5 0.007451938 0.2844037 0.4702381 0.09815951
## 6 0.007451938 0.2828746 0.4702381 0.09969325
## magnet_dumbbell_x magnet_dumbbell_y magnet_dumbbell_z roll_forearm
## 1 0.06801619 0.9196787 0.2759104 0.5788889
## 2 0.07125506 0.9203874 0.2773109 0.5786111
## 3 0.06639676 0.9208599 0.2787115 0.5786111
## 4 0.07368421 0.9220411 0.2829132 0.5780556
## 5 0.07206478 0.9194425 0.2717087 0.5777778
## 6 0.06882591 0.9199150 0.2745098 0.5775000
## pitch_forearm yaw_forearm total_accel_forearm gyros_forearm_x gyros_forearm_y
## 1 0.05298829 0.07500000 0.3333333 0.8482865 0.02207408
## 2 0.05298829 0.07500000 0.3333333 0.8479014 0.02207408
## 3 0.05298829 0.07777778 0.3333333 0.8482865 0.02201119
## 4 0.05298829 0.07777778 0.3333333 0.8479014 0.02201119
## 5 0.05298829 0.07777778 0.3333333 0.8479014 0.02207408
## 6 0.05298829 0.07777778 0.3333333 0.8479014 0.02201119
## gyros_forearm_z accel_forearm_x accel_forearm_y accel_forearm_z
## 1 0.03375298 0.7076923 0.5369775 0.3134328
## 2 0.03375298 0.7076923 0.5369775 0.3120760
## 3 0.03383663 0.7117949 0.5376206 0.3161465
## 4 0.03383663 0.7046154 0.5389068 0.3147897
## 5 0.03375298 0.7046154 0.5389068 0.3147897
## 6 0.03371115 0.7087179 0.5369775 0.3134328
## magnet_forearm_x magnet_forearm_y magnet_forearm_z
## 1 0.6470287 0.6523569 0.7023752
## 2 0.6465164 0.6553030 0.7009210
## 3 0.6465164 0.6540404 0.6989821
## 4 0.6475410 0.6540404 0.6989821
## 5 0.6470287 0.6527778 0.7009210
## 6 0.6511270 0.6548822 0.7033446
Mantenemos una copia etiquetada de los datos normalizados, por si fuera necesaria más adelante.
classe <- df$classe
df_labelled_norm <- cbind(classe, df_norm)
rm(classe) # eliminamos el objeto classe, ya no es necesario
head(df_labelled_norm)
## classe roll_belt pitch_belt yaw_belt total_accel_belt gyros_belt_x
## 1 A 0.1587742 0.5501292 0.2384401 0.1034483 0.3190184
## 2 A 0.1587742 0.5501292 0.2384401 0.1034483 0.3251534
## 3 A 0.1588266 0.5501292 0.2384401 0.1034483 0.3190184
## 4 A 0.1591409 0.5499569 0.2384401 0.1034483 0.3251534
## 5 A 0.1591409 0.5501292 0.2384401 0.1034483 0.3251534
## 6 A 0.1589838 0.5500431 0.2384401 0.1034483 0.3251534
## gyros_belt_y gyros_belt_z accel_belt_x accel_belt_y accel_belt_z
## 1 0.500000 0.4675325 0.4829268 0.3133047 0.7815789
## 2 0.500000 0.4675325 0.4780488 0.3133047 0.7815789
## 3 0.500000 0.4675325 0.4878049 0.3175966 0.7842105
## 4 0.500000 0.4642857 0.4780488 0.3090129 0.7789474
## 5 0.515625 0.4675325 0.4829268 0.3047210 0.7868421
## 6 0.500000 0.4675325 0.4829268 0.3133047 0.7789474
## magnet_belt_x magnet_belt_y magnet_belt_z roll_arm pitch_arm yaw_arm
## 1 0.09124767 0.7680251 0.3384279 0.1444444 0.6277496 0.05277778
## 2 0.08379888 0.7962382 0.3406114 0.1444444 0.6277496 0.05277778
## 3 0.09310987 0.7711599 0.3471616 0.1444444 0.6277496 0.05277778
## 4 0.08566108 0.7836991 0.3417031 0.1444444 0.6254935 0.05277778
## 5 0.08566108 0.7711599 0.3504367 0.1444444 0.6254935 0.05277778
## 6 0.09683426 0.7805643 0.3395197 0.1444444 0.6249295 0.05277778
## total_accel_arm gyros_arm_x gyros_arm_y gyros_arm_z accel_arm_x accel_arm_y
## 1 0.5076923 0.5667260 0.5477707 0.4317757 0.1379310 0.6821086
## 2 0.5076923 0.5685053 0.5445860 0.4317757 0.1355529 0.6837061
## 3 0.5076923 0.5685053 0.5445860 0.4317757 0.1367420 0.6837061
## 4 0.5076923 0.5685053 0.5429936 0.4392523 0.1367420 0.6853035
## 5 0.5076923 0.5667260 0.5429936 0.4355140 0.1367420 0.6853035
## 6 0.5076923 0.5685053 0.5429936 0.4355140 0.1367420 0.6853035
## accel_arm_z magnet_arm_x magnet_arm_y magnet_arm_z roll_dumbbell
## 1 0.5528017 0.1581259 0.7476923 0.8621224 0.5427530
## 2 0.5506466 0.1573939 0.7476923 0.8597986 0.5430087
## 3 0.5495690 0.1581259 0.7548718 0.8597986 0.5420974
## 4 0.5528017 0.1551977 0.7548718 0.8590240 0.5439866
## 5 0.5528017 0.1537335 0.7476923 0.8543765 0.5438157
## 6 0.5538793 0.1573939 0.7528205 0.8597986 0.5438279
## pitch_dumbbell yaw_dumbbell total_accel_dumbbell gyros_dumbbell_x
## 1 0.2645508 0.2158017 0.637931 0.9892348
## 2 0.2640708 0.2163356 0.637931 0.9892348
## 3 0.2652728 0.2149291 0.637931 0.9892348
## 4 0.2648859 0.2158027 0.637931 0.9892348
## 5 0.2647696 0.2158700 0.637931 0.9892348
## 6 0.2634685 0.2171388 0.637931 0.9892348
## gyros_dumbbell_y gyros_dumbbell_z accel_dumbbell_x accel_dumbbell_y
## 1 0.03844732 0.007451938 0.2828746 0.4682540
## 2 0.03844732 0.007451938 0.2844037 0.4682540
## 3 0.03844732 0.007451938 0.2859327 0.4662698
## 4 0.03844732 0.007389317 0.2859327 0.4702381
## 5 0.03844732 0.007451938 0.2844037 0.4702381
## 6 0.03844732 0.007451938 0.2828746 0.4702381
## accel_dumbbell_z magnet_dumbbell_x magnet_dumbbell_y magnet_dumbbell_z
## 1 0.09662577 0.06801619 0.9196787 0.2759104
## 2 0.09969325 0.07125506 0.9203874 0.2773109
## 3 0.09815951 0.06639676 0.9208599 0.2787115
## 4 0.09969325 0.07368421 0.9220411 0.2829132
## 5 0.09815951 0.07206478 0.9194425 0.2717087
## 6 0.09969325 0.06882591 0.9199150 0.2745098
## roll_forearm pitch_forearm yaw_forearm total_accel_forearm gyros_forearm_x
## 1 0.5788889 0.05298829 0.07500000 0.3333333 0.8482865
## 2 0.5786111 0.05298829 0.07500000 0.3333333 0.8479014
## 3 0.5786111 0.05298829 0.07777778 0.3333333 0.8482865
## 4 0.5780556 0.05298829 0.07777778 0.3333333 0.8479014
## 5 0.5777778 0.05298829 0.07777778 0.3333333 0.8479014
## 6 0.5775000 0.05298829 0.07777778 0.3333333 0.8479014
## gyros_forearm_y gyros_forearm_z accel_forearm_x accel_forearm_y
## 1 0.02207408 0.03375298 0.7076923 0.5369775
## 2 0.02207408 0.03375298 0.7076923 0.5369775
## 3 0.02201119 0.03383663 0.7117949 0.5376206
## 4 0.02201119 0.03383663 0.7046154 0.5389068
## 5 0.02207408 0.03375298 0.7046154 0.5389068
## 6 0.02201119 0.03371115 0.7087179 0.5369775
## accel_forearm_z magnet_forearm_x magnet_forearm_y magnet_forearm_z
## 1 0.3134328 0.6470287 0.6523569 0.7023752
## 2 0.3120760 0.6465164 0.6553030 0.7009210
## 3 0.3161465 0.6465164 0.6540404 0.6989821
## 4 0.3147897 0.6475410 0.6540404 0.6989821
## 5 0.3147897 0.6470287 0.6527778 0.7009210
## 6 0.3134328 0.6511270 0.6548822 0.7033446
Recordemos que cada observación del dataset corresponde a una postura durante la realización de un ejercicio. El objetivo es construir y explorar modelos de segmentación que intenten capturar la estructura de grupos existente en el conjunto de datos.
Implementamos clustering jerárquico utilizando la función hclust(), que forma parte del paquete stats que se carga por defecto.
Utilizamos la distancia de Ward, aunque es posible utilizar otro métodos como “single”, “complete”, “average”, etc
hclust.result <- hclust(dist(df_norm), method="ward.D")
plot(hclust.result, labels=df_labelled_norm$classe) # añadimos etiquetas de classe
El número de observaciones es muy elevado, por lo que es normal que no podamos visualizar el detalle de cada observación y su etiqueta. Sin embargo, podremos apreciar la estructura jerárquica del clustering.
Visualmente, podemos seleccionar el número de clúster, por ejemplo:
plot(hclust.result, labels=df_labelled_norm$classe) # añadimos etiquetas de classe
rect.hclust(hclust.result, 4)
plot(hclust.result, labels=df_labelled_norm$classe) # añadimos etiquetas de classe
rect.hclust(hclust.result, 5)
plot(hclust.result, labels=df_labelled_norm$classe) # añadimos etiquetas de classe
rect.hclust(hclust.result, 6)
Podemos podar el árbol obtenido, limitando el número de clúster “k” o la altura “h”. Utilizamos la función cutree(), que devuelve un vector con la asignación de cada observación a un clúster.
Probamos con k= 5 clústers
cut_avg <- cutree(hclust.result, k = 5)
cut_avg[1:10]
## 1 2 3 4 5 6 7 8 9 10
## 1 1 1 1 1 1 1 1 1 1
Añadimos la información de pertenencia a cada clúster. Contamos el número de instancias en cada clúster
df_norm_hclust <- df_norm %>% mutate(cluster = cut_avg)
df_norm_hclust %>% count(cluster)
## # A tibble: 5 x 2
## cluster n
## <int> <int>
## 1 1 6641
## 2 2 2610
## 3 3 3892
## 4 4 3536
## 5 5 2943
Comprobamos contra las etiquetas de clase:
table(df_norm_hclust$cluster, df_labelled_norm$classe)
##
## A B C D E
## 1 1745 1438 1004 1181 1273
## 2 640 505 499 469 497
## 3 1165 776 750 515 686
## 4 899 745 539 642 711
## 5 1131 333 630 409 440
Podemos observar que los clústers hallados mediantes técnicas no supervisadas no coinciden con las etiquetas de clase. Recordemos que, mientras que un modelo de clasificación supervisada es entrenado sobre datos etiquetados y su salida corresponde a los valores de las clases aprendidas, los modelos no supervisados no asumen un número de clases a priori. El modelo de clustering jerárquico estudia la distribución de los datos y trata de identificar grupos según una medida dada de distancia.
Otra opción es seleccionar variables específicas y realizar el clustering sobre estas variables.
Estudiando la matriz de correlaciones, observamos que las variables “magnet_belt_y”, “magnet_belt_z” están correladas con la clase E, mientras que “pitch_forearm” está correlada con la clase D. Si seleccionamos estas columnas, podemos estudiar la correspondencia entre el clustering realizado por hclust() y las etiquetas reales
hclust.result <- hclust(dist(df_norm[colnames(df_norm) %in% c("magnet_belt_y", "magnet_belt_z", "pitch_forearm")]),
method="ward.D")
plot(hclust.result, labels=df_labelled_norm$classe) # añadimos etiquetas de classe
Podemos podar el árbol obtenido, limitando el número de clúster “k” o la altura “h”. Utilizamos la función cutree(), que devuelve un vector con la asignación de cada observación a un clúster.
De nuevo, probamos con k = 5 clusters:
cut_avg <- cutree(hclust.result, k = 5)
cut_avg[1:10]
## 1 2 3 4 5 6 7 8 9 10
## 1 1 1 1 1 1 1 1 1 1
Contamos el número de instancias en cada clúster
df_norm_hclust <- df_norm %>% mutate(cluster = cut_avg)
df_norm_hclust %>% count(cluster)
## # A tibble: 5 x 2
## cluster n
## <int> <int>
## 1 1 1414
## 2 2 3769
## 3 3 5024
## 4 4 8298
## 5 5 1117
Comprobamos contra las etiquetas reales:
table(df_norm_hclust$cluster, df_labelled_norm$classe)
##
## A B C D E
## 1 1414 0 0 0 0
## 2 983 801 770 199 1016
## 3 847 950 809 1626 792
## 4 2336 2046 1843 1155 918
## 5 0 0 0 236 881
Sobre el subconjunto de variables seleccionado, el algoritmo de clustering identifica un clúster formado únicamente por observaciones correspondientes a la clase A y un clúster formado por observaciones de las clase D y E. Los demás clusters contienen observaciones de todas las clases.
En esta sección, utilizamos el algoritmo k-means, buscando calcular el mejor clustering a partir de los datos. Para determinar el número óptimo de clusters, podemos seguir dos aproximaciones:
Utilizar la función fviz_nbclust para determinar y visualizar el número óptimo de clústers, usando diferentes métodos: “within-groups sums of squares” (wss) y buscar el “codo” de la curva, average silhouette o gap statistics.
Usar alguna de las medidas de calidad de clusters, o todas ellas, mediante el paquete NbClust. Podemos pintar el resultado de esta función como un diagrama de barras para verlo gráficamente.
Calculamos el wss y representamos la curva de codo para ver qué número de clusters nos sugiere.
Recordemos que en k=1 existe un único clúster y la wss es máxima, mientras que en k=inf todos los puntos pertenecen a su propio clúster y el wss es cero. La curva desciende rápidamente hasta que el número de clústers alcanza el número de agrupaciones en la distribución de datos.
Nota: recuerda que esta metrica se basa en un cambio abrupto en la curva, lo cual es subjetivo.
Observamos que en k=2, k=4 y k=6 se suaviza la caída de manera apreciable. Entre k=8 y k=9 la wss incluso aumenta.
gc() #provoca recolección de basura, liberando memoria
## used (Mb) gc trigger (Mb) max used (Mb)
## Ncells 2908841 155.4 5014097 267.8 5014097 267.8
## Vcells 7143520 54.6 563040517 4295.7 590750474 4507.1
fviz_nbclust(df_norm, kmeans, k.max = 15, method = "wss") +
geom_vline(xintercept = 4, linetype = 2)
Utilizamos ahora el indicador average silhouette. Según esta métrica, el número óptimo de clústers es 14. Si nos limitamos a valores de k menores de 8, los valores k=2 y k=5 son los mejores candidatos.
gc() #provoca recolección de basura, liberando memoria
## used (Mb) gc trigger (Mb) max used (Mb)
## Ncells 3087205 164.9 5014097 267.8 5014097 267.8
## Vcells 7388243 56.4 1607864784 12267.1 2081448468 15880.2
fviz_nbclust(df_norm, kmeans, k.max = 15, method = "silhouette")
Los resultados no son definitivos, por lo que pasamos a evaluar múltiples métricas utilizando el paquete NbClust.
Calculamos el número óptimo de clusters utilizando el paquete NbClust.
NbClust provee 30 índices para determinar el número de clústers y propone al usuario el mejor esquema de clústering. Fijamos el mínimo número de clústers a 2 y el máximo número de clústers a 15 (valores por defecto).
Es importante destacar que NbClust consume mucha memoria, y en datasets relativamente grandes como el nuestro la ejecución puede fallar con error “Error: cannot allocate vector of size XX”, donde XX es el tamaño del vector. Hemos eliminado los índices que más memoria utilizan y conseguido que la ejecución finalice con éxito. Los índices eliminados son: “silhouette”, “ptbiserial”, “gap”, “frey”, “mcclain”, “gamma”, “gplus”, “tau”, “hubert”.
Como la función NbClust no permite ejecutar un conjunto personalizado de índices (o todos o uno en particular) tendremos que recorrer la lista de índices manualmente y recopilar la información nosotros.
Finalmente, procedemos a mostrar un resumen del número de índices que han escogido cada número de clusters y a representar esta misma información gráficamente.
gc() #provoca recolección de basura, liberando memoria al reclamar memoria ocupada por objetos que no están ya en uso
## used (Mb) gc trigger (Mb) max used (Mb)
## Ncells 3088939 165.0 5014097 267.8 5014097 267.8
## Vcells 7395212 56.5 1286291828 9813.7 2081448468 15880.2
# indices <- c("kl", "ch", "hartigan", "ccc", "scott", "marriot", "trcovw", "tracew", "friedman", "rubin", "cindex", "db", "silhouette", "duda", "pseudot2", "beale", "ratkowsky", "ball", "ptbiserial", "gap", "frey", "mcclain", "gamma", "gplus", "tau", "dunn", "hubert", "sdindex", "dindex", "sdbw")
# indices <- c("gamma", "gplus", "tau")
indices <- c("kl", "ch", "hartigan", "ccc", "scott", "marriot", "trcovw", "tracew", "friedman", "rubin", "cindex", "db", "duda", "pseudot2", "beale", "ratkowsky", "ball", "dunn", "sdindex", "dindex", "sdbw")
best_clusters <- rep(0, 15)
for (i in 1:length(indices)) {
print(indices[i])
nc <- NbClust(df_norm, min.nc=2, max.nc=15, method="kmeans", index=indices[i])
best_clusters[nc$Best.nc[1]]=best_clusters[nc$Best.nc[1]]+1
print("índice completado")
}
## [1] "kl"
## [1] "índice completado"
## [1] "ch"
## [1] "índice completado"
## [1] "hartigan"
## [1] "índice completado"
## [1] "ccc"
## [1] "índice completado"
## [1] "scott"
## [1] "índice completado"
## [1] "marriot"
## [1] "índice completado"
## [1] "trcovw"
## [1] "índice completado"
## [1] "tracew"
## [1] "índice completado"
## [1] "friedman"
## [1] "índice completado"
## [1] "rubin"
## [1] "índice completado"
## [1] "cindex"
## [1] "índice completado"
## [1] "db"
## [1] "índice completado"
## [1] "duda"
## [1] "índice completado"
## [1] "pseudot2"
## [1] "índice completado"
## [1] "beale"
## [1] "índice completado"
## [1] "ratkowsky"
## [1] "índice completado"
## [1] "ball"
## [1] "índice completado"
## [1] "dunn"
## [1] "índice completado"
## [1] "sdindex"
## [1] "índice completado"
## [1] "dindex"
## *** : The D index is a graphical method of determining the number of clusters.
## In the plot of D index, we seek a significant knee (the significant peak in Dindex
## second differences plot) that corresponds to a significant increase of the value of
## the measure.
##
## [1] "índice completado"
## [1] "sdbw"
## [1] "índice completado"
print(best_clusters)
## [1] 0 2 6 1 2 3 0 0 3 0 0 0 0 1 2
par(mfrow = c(1, 1))
barplot(best_clusters, xlab="Numer of Clusters", ylab="Number of Criteria", main="Number of Clusters Chosen by 21 Criteria", names.arg = 1:15)
Observamos que la mayoría de índices optan por 3 clústers, por lo que tomaremos este valor como referencia.
Calculemos k-means con el número óptimo de clusters: k=3. Utilizamos el parámetro nstart para seleccionar el número de veces que el algoritmo debe escoger los centroides iniciales. Esto alivia el problema de inicialización del algoritmo y lo hace más robusto.
nClusters <- 3
fit.km <- kmeans(df_norm, nClusters, nstart=25)
print(fit.km$centers)
## roll_belt pitch_belt yaw_belt total_accel_belt gyros_belt_x gyros_belt_y
## 1 0.7978260 0.6520883 0.5127548 0.6569510 0.2815004 0.5413976
## 2 0.8233997 0.1240591 0.9380867 0.6251462 0.3546263 0.5865738
## 3 0.1546993 0.5208422 0.2528657 0.1235033 0.3251057 0.5016165
## gyros_belt_z accel_belt_x accel_belt_y accel_belt_z magnet_belt_x
## 1 0.3814798 0.4422150 0.5736548 0.2712299 0.1262086
## 2 0.4190589 0.8242887 0.4817486 0.2905738 0.4165408
## 3 0.4689231 0.5242650 0.3077671 0.7985950 0.1601507
## magnet_belt_y magnet_belt_z roll_arm pitch_arm yaw_arm total_accel_arm
## 1 0.7199881 0.2875618 0.4890390 0.4559008 0.4702986 0.3371899
## 2 0.7599030 0.3270579 0.4563814 0.5301997 0.4268976 0.3266345
## 3 0.7679649 0.3030659 0.6261450 0.4644918 0.5452143 0.4230946
## gyros_arm_x gyros_arm_y gyros_arm_z accel_arm_x accel_arm_y accel_arm_z
## 1 0.5683900 0.4858289 0.5209275 0.5126318 0.4339582 0.6825509
## 2 0.5880723 0.4611194 0.5745281 0.3717211 0.4061243 0.6362067
## 3 0.5647813 0.5388690 0.4274139 0.3571728 0.7034369 0.5499090
## magnet_arm_x magnet_arm_y magnet_arm_z roll_dumbbell pitch_dumbbell
## 1 0.5971574 0.5693306 0.7079904 0.4528123 0.5050067
## 2 0.5943772 0.5593807 0.7054973 0.7010448 0.4237197
## 3 0.5383430 0.5597514 0.6923120 0.6080415 0.4546090
## yaw_dumbbell total_accel_dumbbell gyros_dumbbell_x gyros_dumbbell_y
## 1 0.7045686 0.1269567 0.9901853 0.04019575
## 2 0.2080208 0.3174460 0.9899282 0.04020019
## 3 0.4849341 0.2739246 0.9899429 0.03911412
## gyros_dumbbell_z accel_dumbbell_x accel_dumbbell_y accel_dumbbell_z
## 1 0.007020904 0.6436975 0.3456884 0.5781482
## 2 0.007165380 0.5827837 0.5808557 0.3088489
## 3 0.007017842 0.5726590 0.5240091 0.4322940
## magnet_dumbbell_x magnet_dumbbell_y magnet_dumbbell_z roll_forearm
## 1 0.4829099 0.8530606 0.2611368 0.5800866
## 2 0.1139064 0.9252548 0.4458319 0.5000000
## 3 0.1654710 0.9252940 0.5348229 0.6410185
## pitch_forearm yaw_forearm total_accel_forearm gyros_forearm_x gyros_forearm_y
## 1 0.6045025 0.4614358 0.2928418 0.8481614 0.02208778
## 2 0.4467036 0.5000000 0.3781023 0.8842938 0.02384698
## 3 0.4805640 0.6339669 0.3167654 0.8438315 0.02182931
## gyros_forearm_z accel_forearm_x accel_forearm_y accel_forearm_z
## 1 0.03384744 0.3556169 0.4537660 0.5154201
## 2 0.03587553 0.3624194 0.6074771 0.5957017
## 3 0.03429686 0.5410481 0.5099078 0.5129412
## magnet_forearm_x magnet_forearm_y magnet_forearm_z
## 1 0.4419144 0.5338565 0.7033260
## 2 0.4945784 0.5577800 0.7223659
## 3 0.5304557 0.5307534 0.6118853
Recordemos que cada observación corresponde a una postura durante la realización del ejercicio. Hemos agrupado las posturas en tres grupos, caracterizados por la media de cada variable en ese grupo (“Cluster means”)
Realizamos un análisis de componentes principales sobre nuestros datos de entrada
pca <- prcomp(df_norm, scale. = T, center = T)
summary(pca)
## Importance of components:
## PC1 PC2 PC3 PC4 PC5 PC6 PC7
## Standard deviation 2.8908 2.8466 2.16241 2.03215 1.91101 1.73308 1.49665
## Proportion of Variance 0.1607 0.1558 0.08992 0.07942 0.07023 0.05776 0.04308
## Cumulative Proportion 0.1607 0.3165 0.40646 0.48587 0.55610 0.61386 0.65694
## PC8 PC9 PC10 PC11 PC12 PC13 PC14
## Standard deviation 1.43973 1.31043 1.22834 1.17707 1.06266 0.99331 0.94377
## Proportion of Variance 0.03986 0.03302 0.02902 0.02664 0.02172 0.01897 0.01713
## Cumulative Proportion 0.69680 0.72983 0.75884 0.78549 0.80720 0.82618 0.84331
## PC15 PC16 PC17 PC18 PC19 PC20 PC21
## Standard deviation 0.91436 0.88840 0.82337 0.78085 0.72968 0.69631 0.65241
## Proportion of Variance 0.01608 0.01518 0.01304 0.01173 0.01024 0.00932 0.00819
## Cumulative Proportion 0.85938 0.87456 0.88760 0.89932 0.90956 0.91889 0.92707
## PC22 PC23 PC24 PC25 PC26 PC27 PC28
## Standard deviation 0.63134 0.61862 0.58250 0.55471 0.54126 0.50596 0.48606
## Proportion of Variance 0.00767 0.00736 0.00653 0.00592 0.00563 0.00492 0.00454
## Cumulative Proportion 0.93474 0.94210 0.94862 0.95454 0.96017 0.96510 0.96964
## PC29 PC30 PC31 PC32 PC33 PC34 PC35
## Standard deviation 0.45105 0.42413 0.41245 0.36296 0.34904 0.33533 0.30328
## Proportion of Variance 0.00391 0.00346 0.00327 0.00253 0.00234 0.00216 0.00177
## Cumulative Proportion 0.97355 0.97701 0.98028 0.98282 0.98516 0.98732 0.98909
## PC36 PC37 PC38 PC39 PC40 PC41 PC42
## Standard deviation 0.28235 0.25340 0.23778 0.23492 0.20199 0.19520 0.18830
## Proportion of Variance 0.00153 0.00123 0.00109 0.00106 0.00078 0.00073 0.00068
## Cumulative Proportion 0.99062 0.99186 0.99295 0.99401 0.99479 0.99553 0.99621
## PC43 PC44 PC45 PC46 PC47 PC48 PC49
## Standard deviation 0.18365 0.17949 0.16946 0.16387 0.14718 0.1435 0.11607
## Proportion of Variance 0.00065 0.00062 0.00055 0.00052 0.00042 0.0004 0.00026
## Cumulative Proportion 0.99686 0.99748 0.99803 0.99854 0.99896 0.9994 0.99962
## PC50 PC51 PC52
## Standard deviation 0.10897 0.07721 0.04636
## Proportion of Variance 0.00023 0.00011 0.00004
## Cumulative Proportion 0.99984 0.99996 1.00000
Observamos que las dos primeras componentes proporcionan algo más del 30% de la información del conjunto.
Aplicamos una transformación en componentes principales, rotando el espacio de variables originales a las componentes principales. Adicionalmente, añadimos la etiqueta de cada clúster:
new_features <- predict(pca, newdata = df_norm)
pca.dat <- as.data.frame(cbind(new_features, group=fit.km$cluster))
Visualizamos los datos. Para añadir interactividad a los gráficos, usamos la biblioteca ggplotly, que nos permite acceder a información adicional al posicionarnos sobre un punto de interés.
gg2 <- ggplot(pca.dat) +
geom_point(aes(x=PC1, y=PC2, col=factor(group), text=rownames(pca.dat)), size=2) +
labs(title = "Visualizing K-Means Clusters Against First Two Principal Components") +
scale_color_brewer(name="", palette = "Set1")
## Warning: Ignoring unknown aesthetics: text
ggplotly(gg2, tooltip = c("text", "x", "y")) %>%
layout(legend = list(x=.9, y=.99))
Observamos que los tres clústers aparecen bien diferenciados.
Aunque el número óptimo de clústers fue k=3, observamos que, proyectando sobre las dos primeras componentes principales, parece que el clúster número uno se podría separar en dos subgrupos.
Podemos incluso representar los datos en 3D, utilizando las tres primeras componentes principales, que proporcionan algo más del 40% de la información del conjunto.
fig <- plot_ly(x= pca.dat$PC1, y= pca.dat$PC2 , z= pca.dat$PC3, type="scatter3d", mode="markers", color=factor(pca.dat$group), colors=c('red2', 'blue2', 'green3'))
fig <- fig %>% layout(title = 'Visualizing K-Means Clusters Against First Three Principal Components',
scene = list(xaxis = list(title = 'PC1'), yaxis = list(title = 'PC2'), zaxis = list(title = 'PC3')))
fig
Podemos confirmar que los clúster 1 y 3 tienen puntos cercanos, que pueden ser problemáticos a la hora de ser asignados. Sin embargo, los resultados de k-means son muy buenos.
La representación en 3D nos permite observar un punto perteneciente al clúster 3 muy alejado de los demás puntos, que probablemente debería ser tratado en la fase de preprocesado, ya que puede afectar a la bondad del clustering.
Por último, podemos estudiar en profundidad el dataset, caracterizando cada clúster según el contexto y objetivo de negocio. Para ello, puede ser útil seleccionar las variables originales con mayor relevancia para nuestro problema y estudiar como se distribuyen en cada clúster, calculando sus estadísticos.
También podemos pintar los clusters únicamente con dos coordenadas, por ejemplo:
plot(df_norm[,c(2,5)], col = fit.km$cluster)
y finalmente podemos comparar contra las etiquetas de clase del dataset etiquetado, para entender qué composición de clases tiene cada clúster
df_norm_hclust_label <- as.data.frame(cbind(df_labelled_norm, group=fit.km$cluster))
df_norm_hclust_label %>%
group_by(group, classe) %>%
count(classe) %>%
group_by(group) %>%
mutate(classe_perc = round(n/sum(n)*100, 2)) %>%
distinct(group, classe, classe_perc)
## # A tibble: 15 x 3
## # Groups: group [3]
## group classe classe_perc
## <int> <fct> <dbl>
## 1 1 A 25.0
## 2 1 B 20.3
## 3 1 C 16.9
## 4 1 D 18.1
## 5 1 E 19.7
## 6 2 A 29.9
## 7 2 B 19.9
## 8 2 C 19.3
## 9 2 D 13.2
## 10 2 E 17.6
## 11 3 A 30.0
## 12 3 B 18.5
## 13 3 C 17.0
## 14 3 D 16.6
## 15 3 E 17.9
o cómo se reparten las clases en cada grupo
df_norm_hclust_label <- as.data.frame(cbind(df_labelled_norm, group=fit.km$cluster))
df_norm_hclust_label %>%
group_by(classe, group) %>%
count(group) %>%
group_by(classe) %>%
mutate(group_perc = round(n/sum(n)*100, 2)) %>%
distinct(classe, group, group_perc)
## # A tibble: 15 x 3
## # Groups: classe [5]
## classe group group_perc
## <fct> <int> <dbl>
## 1 A 1 27.6
## 2 A 2 20.9
## 3 A 3 51.5
## 4 B 1 32.9
## 5 B 2 20.4
## 6 B 3 46.6
## 7 C 1 30.3
## 8 C 2 21.9
## 9 C 3 47.8
## 10 D 1 34.6
## 11 D 2 16.0
## 12 D 3 49.4
## 13 E 1 33.5
## 14 E 2 19.0
## 15 E 3 47.5
Concluímos que los clústers contienen una mezcla de las 5 etiquetas del dataset inicial.
Aplicamos ahora el algoritmo K-medoids. En particular, utilizamos dos métodos:
K-medoids un algoritmo muy similar al k-means. La principal diferencia es que se usa el punto más cercano al centroide como representante del cluster, lo que hace que k-medoids sea más robusto que k-means cuando el dataset contiene outliers.
Nota: medoide es un concepto similar a centroide, pero los medoides siempre están restringidos a ser miembros del conjunto de datos.
Utilizamos PAM (Partition Around Medoids) del paquete cluster. Para evaluar el número de clúster, utilizaremos la métrica silhouette. El valor de la anchura de silhouette se interpreta como sigue:
La implementación de PAM provee la anchura de silhouette media por clúster y total.
Calculamos el clustering fijando el número de clusters k=3
pam.result<-pam(df_norm, k=3)
Representamos gráficamente:
layout(matrix(c(1,2), 1, 2))
plot(pam.result)
layout(matrix(1))
Observamos que, utilizando k-medoids, el clúster etiquetado como número 2 no está muy diferenciado de los demás. El índice de anchura de silhouette indica que el clúster no está bien diferenciado.
Vamos a confirmar este punto. Llevamos a cabo un análisis de componentes principales y usamos las dos primeras para visualizar los datos.
#new_features <- predict(pca, newdata = df_norm) #No es necesario volver a ejecutar esta línea, es solo informativa
pca.dat <- as.data.frame(cbind(new_features, group=pam.result$clustering))
Visualizamos los datos. Para añadir interactivdad a los gráficos, usamos la biblioteca ggplotly, que nos permite acceder a información adicional al posicionarnos sobre un punto de interés.
gg2 <- ggplot(pca.dat) +
geom_point(aes(x=PC1, y=PC2, col=factor(group), text=rownames(pca.dat)), size=2) +
labs(title = "Visualizing K-Means Clusters Against First Two Principal Components") +
scale_color_brewer(name="", palette = "Set1")
## Warning: Ignoring unknown aesthetics: text
ggplotly(gg2, tooltip = c("text", "x", "y")) %>%
layout(legend = list(x=.9, y=.99))
Podemos incluso representar los datos en 3D, utilizando las tres primeras componentes principales, que proporcionan algo más del 40% de la información del conjunto.
fig <- plot_ly(x= pca.dat$PC1, y= pca.dat$PC2 , z= pca.dat$PC3, type="scatter3d", mode="markers", color=factor(pca.dat$group), colors=c('red2', 'blue2', 'green3'))
fig <- fig %>% layout(title = 'Visualizing K-Means Clusters Against First Three Principal Components',
scene = list(xaxis = list(title = 'PC1'), yaxis = list(title = 'PC2'), zaxis = list(title = 'PC3')))
fig
Efectivamente, confirmamos que el clúster 2 (en azul) se mezcla con el clúster 1 y el clúster 3. En el grupo de observaciones del clúster 1 aparece múltiples puntos asignado al clúster 2, y en el grupo de observaciones del clúster 2 aparecen múltiples puntos asignados al clúster 3.
Podemos probar a ejercutar el modelo de nuevo, fijando el número de clusters k=4
pam.result<-pam(df_norm, k=4)
Representamos gráficamente:
layout(matrix(c(1,2), 1, 2))
plot(pam.result)
layout(matrix(1))
Observamos que sigue existiendo mezcla: el índice para los clústers 1 y 3 sigue siendo muy bajo, aunque la media del índice para todos los clústers mejora ligeramente.
Utilizando pamk, podemos calcular el clustering sin fijar el número de clústers. El parámetro krange determina el número de clústers a estimar, por defecto toma el valor de 2 a 10.
pamk.result<-pamk(df_norm, krange=2:10)
Representamos graficamente
layout(matrix(c(1,2), 1, 2))
plot(pamk.result$pamobject)
layout(matrix(1))
El algoritmo determina que k=2 es el número óptimo de clústers. Este número probablemente es demasiado pequeño para ser de utilidad real, ya que solo permite clasificar de manera binaria.
Probemos a fijar el parámetro krange como 3:10, evaluando únicamente un número de clústers entre 3 y 10.
pamk.result<-pamk(df_norm, krange=3:10)
Representamos graficamente
layout(matrix(c(1,2), 1, 2))
plot(pamk.result$pamobject)
layout(matrix(1))
En este caso, PAM determina que existen 5 clústers. El valor medio de la anchura de silhouette es similar al del caso anterior, aunque podemos ver que el valor del índice para el clúster 5 es bastante bajo.
De nuevo, llevamos a cabo un análisis de componentes principales y usamos las dos primeras para visualizar los datos.
#new_features <- predict(pca, newdata = df_norm) #No es necesario volver a ejecutar esta línea, es solo informativa
pca.dat <- as.data.frame(cbind(new_features, group=pamk.result$pamobject$clustering))
Visualizamos los datos. Para añadir interactivdad a los gráficos, usamos la biblioteca ggplotly, que nos permite acceder a información adicional al posicionarnos sobre un punto de interés.
gg2 <- ggplot(pca.dat) +
geom_point(aes(x=PC1, y=PC2, col=factor(group), text=rownames(pca.dat)), size=2) +
labs(title = "Visualizing K-Means Clusters Against First Two Principal Components") +
scale_color_brewer(name="", palette = "Set1")
## Warning: Ignoring unknown aesthetics: text
ggplotly(gg2, tooltip = c("text", "x", "y")) %>%
layout(legend = list(x=.9, y=.99))
Podemos incluso representar los datos en 3D, utilizando las tres primeras componentes principales, que proporcionan algo más del 40% de la información del conjunto.
fig <- plot_ly(x= pca.dat$PC1, y= pca.dat$PC2 , z= pca.dat$PC3, type="scatter3d", mode="markers", color=factor(pca.dat$group), colors=c('red2', 'blue2', 'green3', 'magenta2', 'orange'))
fig <- fig %>% layout(title = 'Visualizing K-Means Clusters Against First Three Principal Components',
scene = list(xaxis = list(title = 'PC1'), yaxis = list(title = 'PC2'), zaxis = list(title = 'PC3')))
fig
Observamos que, proyectando sobre las tres primeras componentes principales, la separación de las observaciones en 5 grupos utilizando k-medoids no produce buenos resultados. Observaciones asignadas a distintos clúster se entremezclan y parece que el algoritmo tiene problemas para asignar los puntos correctamente.
Recordemos que estamos proyectando únicamente sobre 3 componentes, que proporcionan alrededor del 40 % de la información, por lo que existe pérdida de información. Sin embargo, después de ejecutar k-medoids con distinto número de clústers, estudiando el índice de silhouette y la proyección sobre las primeras componentes principales para cada uno de los modelos, podemos concluir que, en comparación, k-means produjo mejores resultados sobre nuestro dataset. En nuestro caso, los modelos de clustering basados en centroides funcionan mejor que los modelos basados en medoides.
Finalmente podemos estudiar cómo se distribuyen las clases para k-medoids con k=5
df_norm_hclust_label <- as.data.frame(cbind(df_labelled_norm, group=pamk.result$pamobject$clustering))
df_norm_hclust_label %>%
group_by(classe, group) %>%
count(group) %>%
group_by(classe) %>%
mutate(group_perc = round(n/sum(n)*100, 2)) %>%
distinct(classe, group, group_perc)
## # A tibble: 25 x 3
## # Groups: classe [5]
## classe group group_perc
## <fct> <int> <dbl>
## 1 A 1 40.1
## 2 A 2 11.4
## 3 A 3 16.2
## 4 A 4 20.9
## 5 A 5 11.4
## 6 B 1 24.8
## 7 B 2 12.6
## 8 B 3 20.3
## 9 B 4 20.0
## 10 B 5 22.3
## # ... with 15 more rows
De nuevo, cada clúster contiene representantes de todas las clases.
En esta sección implementamos el algoritmo Expectation-Maximization (EM). Este algoritmo intenta aprender la distribución de los datos de cada conjunto, estudiando:
Existentes distintas variantes, en función de los grados de libertad de las distribuciones:
Por último, la pertenencia de un punto a un conjunto se expresa en términos de probabilidad.
Utilizamos el paquete Mclust, que implementa el algoritmo EM. Permite ajustar distintos tipos de distribuciónes y puede evaluar simultáneamente distintos números de clústers y devolver el más apropiado de acuerdo a una medida.
El parámetro “G” toma un entero o vector de enteros con el número de clústers que desea probar. Por defecto, toma el valor G=1:9 y prueba todos estos modelos
Mclust.result <- Mclust(df_norm) # si no especificas hace 1 a 9 clústers, y todos los posibles modelos
Podemos pintar la gráfica de evolución del BIC (Bayesian Information Criterion) para ver qué modelo se ajusta mejor.
# Notar que la interpretación del BIC en R es al revés de la interp. en Python
## En R: el más positvo, en Python el más negativo
plot(Mclust.result, data=df_norm, what="BIC")
summary(Mclust.result$BIC)
## Best BIC values:
## VEV,9 VEV,8 VEV,7
## BIC 4574406 4414323.8 4369613.8
## BIC diff 0 -160082.4 -204792.5
El mejor modelo es VEV (distribución elipsoidal, volumen variable, misma forma, orientación variable) con 9 clústers, aunque los resultados con 7 y 8 clústers también son buenos.
El modelo EEV (distribución elipsoidal, mismo volumen, misma forma, orientación variable) también produce buenos resultados, aunque ligeramente peores que VEV. Los modelos con distribución elipsoidal son los que mejores resultados producen.
Utilizamos el mejor modelo: VEV con 9 clústers. Podemos obtener la asignación de cada observación a uno de los 9 clúster (hard prediction):
head(Mclust.result$classification, 5)
## 1 2 3 4 5
## 4 4 4 4 4
o la probabilidad de que cada observación pertenezca a un cluster (soft prediction):
head(round(Mclust.result$z, 2), 5)
## [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
## 1 0 0 0 1 0 0 0 0 0
## 2 0 0 0 1 0 0 0 0 0
## 3 0 0 0 1 0 0 0 0 0
## 4 0 0 0 1 0 0 0 0 0
## 5 0 0 0 1 0 0 0 0 0
Podemos visualizar los clusters como una matrix de scatter plot, para cada combinación de variables. Por ejemplo, para las 4 primeras columnas:
plot(Mclust.result, dimens = 1:4, what="classification")
También podemos representar la densidad estimada
plot(Mclust.result, dimens = 1:4, what="density")
plot(Mclust.result, dimens = 4:5, what = "density", type = "persp")
y representar la incertidumbre en la clasificación
plot(Mclust.result, dimens = 1:4, what="uncertainty")
Por último, podemos llevar a cabo un análisis de componentes principales y usar las dos primeras para visualizar los datos. Utilizamos la descomposición realizada en las secciones anteriores
summary(pca)
## Importance of components:
## PC1 PC2 PC3 PC4 PC5 PC6 PC7
## Standard deviation 2.8908 2.8466 2.16241 2.03215 1.91101 1.73308 1.49665
## Proportion of Variance 0.1607 0.1558 0.08992 0.07942 0.07023 0.05776 0.04308
## Cumulative Proportion 0.1607 0.3165 0.40646 0.48587 0.55610 0.61386 0.65694
## PC8 PC9 PC10 PC11 PC12 PC13 PC14
## Standard deviation 1.43973 1.31043 1.22834 1.17707 1.06266 0.99331 0.94377
## Proportion of Variance 0.03986 0.03302 0.02902 0.02664 0.02172 0.01897 0.01713
## Cumulative Proportion 0.69680 0.72983 0.75884 0.78549 0.80720 0.82618 0.84331
## PC15 PC16 PC17 PC18 PC19 PC20 PC21
## Standard deviation 0.91436 0.88840 0.82337 0.78085 0.72968 0.69631 0.65241
## Proportion of Variance 0.01608 0.01518 0.01304 0.01173 0.01024 0.00932 0.00819
## Cumulative Proportion 0.85938 0.87456 0.88760 0.89932 0.90956 0.91889 0.92707
## PC22 PC23 PC24 PC25 PC26 PC27 PC28
## Standard deviation 0.63134 0.61862 0.58250 0.55471 0.54126 0.50596 0.48606
## Proportion of Variance 0.00767 0.00736 0.00653 0.00592 0.00563 0.00492 0.00454
## Cumulative Proportion 0.93474 0.94210 0.94862 0.95454 0.96017 0.96510 0.96964
## PC29 PC30 PC31 PC32 PC33 PC34 PC35
## Standard deviation 0.45105 0.42413 0.41245 0.36296 0.34904 0.33533 0.30328
## Proportion of Variance 0.00391 0.00346 0.00327 0.00253 0.00234 0.00216 0.00177
## Cumulative Proportion 0.97355 0.97701 0.98028 0.98282 0.98516 0.98732 0.98909
## PC36 PC37 PC38 PC39 PC40 PC41 PC42
## Standard deviation 0.28235 0.25340 0.23778 0.23492 0.20199 0.19520 0.18830
## Proportion of Variance 0.00153 0.00123 0.00109 0.00106 0.00078 0.00073 0.00068
## Cumulative Proportion 0.99062 0.99186 0.99295 0.99401 0.99479 0.99553 0.99621
## PC43 PC44 PC45 PC46 PC47 PC48 PC49
## Standard deviation 0.18365 0.17949 0.16946 0.16387 0.14718 0.1435 0.11607
## Proportion of Variance 0.00065 0.00062 0.00055 0.00052 0.00042 0.0004 0.00026
## Cumulative Proportion 0.99686 0.99748 0.99803 0.99854 0.99896 0.9994 0.99962
## PC50 PC51 PC52
## Standard deviation 0.10897 0.07721 0.04636
## Proportion of Variance 0.00023 0.00011 0.00004
## Cumulative Proportion 0.99984 0.99996 1.00000
#new_features <- predict(pca, newdata = df_norm) #No es necesario volver a ejecutar esta línea, es solo informativa
pca.dat <- as.data.frame(cbind(new_features, group=Mclust.result$classification))
Visualizamos los datos. Para añadir interactividad a los gráficos, usamos la biblioteca ggplotly, que nos permite acceder a información adicional al posicionarnos sobre un punto de interés.
gg2 <- ggplot(pca.dat) +
geom_point(aes(x=PC1, y=PC2, col=factor(group), text=rownames(pca.dat)), size=2) +
labs(title = "Visualizing K-Means Clusters Against First Two Principal Components") +
scale_color_brewer(name="", palette = "Set1")
## Warning: Ignoring unknown aesthetics: text
ggplotly(gg2, tooltip = c("text", "x", "y")) %>%
layout(legend = list(x=.9, y=.99))
Como era de esperar, el número de clústers es muy elevado y varios clúster solapan entre sí.
Podemos incluso representar los datos en 3D, utilizando las tres primeras componentes principales, que proporcionan algo más del 40% de la información del conjunto.
fig <- plot_ly(x= pca.dat$PC1, y= pca.dat$PC2 , z= pca.dat$PC3, type="scatter3d", mode="markers", color=factor(pca.dat$group), colors=c('red2', 'blue2', 'green3', 'magenta3', 'orange', 'yellow', 'brown2', 'pink', 'gray'))
fig <- fig %>% layout(title = 'Visualizing K-Means Clusters Against First Three Principal Components',
scene = list(xaxis = list(title = 'PC1'), yaxis = list(title = 'PC2'), zaxis = list(title = 'PC3')))
fig
La visualización en 3D permite estudiar más detalles y observar mejor la frontera entre clústers. Observamos que los clústers 5 y 6 (naranja y amarillo) están bien diferenciados. Sin embargo, los demás se entremezclan en dos grandes grupos.
Por otro lado, es interesante observar que, mientras que el clustering basado en centroides (k-means) estimaba un número óptimo de clústers igual a 3, EM no funciona muy bien sobre este número de clústers.
Podemos estudiar los resultados de EM si fijamos el número de clústers igual a 3:
Mclust.result <- Mclust(df_norm, G=3)
Representamos la gráfica de evolución del BIC (Bayesian Information Criterion) para ver qué modelo se ajusta mejor.
# Notar que la interpretación del BIC en R es al revés de la interp. en Python
## En R: el más positvo, en Python el más negativo
plot(Mclust.result, data=df_norm, what="BIC")
summary(Mclust.result$BIC)
## Best BIC values:
## VEV,3 EEV,3 EEE,3
## BIC 3573457 3391105.1 3046333.6
## BIC diff 0 -182352.3 -527123.8
De nuevo, el mejor modelo es VEV (distribución elipsoidal, volumen variable, misma forma, orientación variable), esta vez con 3 clúster porque así lo hemos forzado.
Aplicamos PCA
#new_features <- predict(pca, newdata = df_norm) #No es necesario volver a ejecutar esta línea, es solo informativa
pca.dat <- as.data.frame(cbind(new_features, group=Mclust.result$classification))
Visualizamos los datos. Para añadir interactividad a los gráficos, usamos la biblioteca ggplotly, que nos permite acceder a información adicional al posicionarnos sobre un punto de interés.
gg2 <- ggplot(pca.dat) +
geom_point(aes(x=PC1, y=PC2, col=factor(group), text=rownames(pca.dat)), size=2) +
labs(title = "Visualizing K-Means Clusters Against First Two Principal Components") +
scale_color_brewer(name="", palette = "Set1")
## Warning: Ignoring unknown aesthetics: text
ggplotly(gg2, tooltip = c("text", "x", "y")) %>%
layout(legend = list(x=.9, y=.99))
Representamos los datos en 3D, utilizando las tres primeras componentes principales, que proporcionan algo más del 40% de la información del conjunto.
fig <- plot_ly(x= pca.dat$PC1, y= pca.dat$PC2 , z= pca.dat$PC3, type="scatter3d", mode="markers", color=factor(pca.dat$group), colors=c('red2', 'blue2', 'green3'))
fig <- fig %>% layout(title = 'Visualizing K-Means Clusters Against First Three Principal Components',
scene = list(xaxis = list(title = 'PC1'), yaxis = list(title = 'PC2'), zaxis = list(title = 'PC3')))
fig
Concluimos que los resultados de EM para k=3 no son muy buenos, como vimos al estudiar el BIC de modelos con entre 1 a 9 clústers.
Modelos con un número mayor de clústers funcionarán mejor, según el BIC, aunque estudiando el modelo para k=9 vimos que los resultados tampoco eran totalmente satisfactorios.
En esta última sección implementamos el clustering basado en densidad (DBSCAN). Este tipo de métodos se basa en la premisa de que los clúster son zonas de alta densidad de puntos separadas por zonas de baja densidad de puntos.
Esto permite que puedan identificar clúster de forma arbitaria y que trabajen bien en presencia de ruido.
Utilizaremos el paquete dbscan para implementar este algoritmo. Primero, debemos escoger los valores para los parámetros MinPts y eps. Habitualmente, se suele probar con varios valores de MinPts y pintar la curva de codo para los k-vecinos de cada punto ordenados y se selecciona eps como la altura a la que se produce un cambio en la pendiente de la curva (aproximadamente, puede ser necesario hacer pequeños ajustes).
Utilizaremos la función kNNdistplot para representar este tipo de curva, que recibe como argumento el dataset y el número de vecinos (k) que queremos probar. Para hacer más fácil la obtención del valor de cambio de pendiente, podemos probar a pintar varias líneas horizontales con la función abline a distintas alturas.
El valor de k, como se ha dicho anteriormente, podemos hacerlo variar, aunque muchas veces se suele escoger el número de variables más una.
Una vez escogido el valor de los parámetros, podemos probar a realizar el clustering y comprobar, mediante su visualización, si los distintos conjuntos de puntos son detectados correctamente.
Procedemos a pintar la curva de codo y a pintar un par de líneas de referencia para intentar ajustar el punto de corte. Nuestro dataset (sin la etiqueta de clase) tiene 52 columnas, por lo que probamos k=52+1
kNNdistplot(df_norm, k = 53)
abline(h=1, col="green")
Seleccionamos el punto de corte y ejecutamos el clustering.
db <- dbscan(df_norm, eps=1, minPts=53)
Mostramos un resumen del objeto devuelto tras hacer el clustering.
str(db)
## List of 3
## $ cluster: int [1:19622] 1 1 1 1 1 1 1 1 1 1 ...
## $ eps : num 1
## $ minPts : num 53
## - attr(*, "class")= chr [1:2] "dbscan_fast" "dbscan"
El modelo diferencia 4 clústers:
unique(db$cluster)
## [1] 1 2 3 0
Representamos los resultados, para observar que el clustering captura razonablemente bien la mayoría de los puntos en clusters bien diferenciados.
plot(df_norm[1:5], col=db$cluster+1L)
También podemos llevar a cabo un análisis de componentes principales y usar las dos primeras para visualizar los datos. Utilizamos la descomposición realizada en las secciones anteriores
summary(pca)
## Importance of components:
## PC1 PC2 PC3 PC4 PC5 PC6 PC7
## Standard deviation 2.8908 2.8466 2.16241 2.03215 1.91101 1.73308 1.49665
## Proportion of Variance 0.1607 0.1558 0.08992 0.07942 0.07023 0.05776 0.04308
## Cumulative Proportion 0.1607 0.3165 0.40646 0.48587 0.55610 0.61386 0.65694
## PC8 PC9 PC10 PC11 PC12 PC13 PC14
## Standard deviation 1.43973 1.31043 1.22834 1.17707 1.06266 0.99331 0.94377
## Proportion of Variance 0.03986 0.03302 0.02902 0.02664 0.02172 0.01897 0.01713
## Cumulative Proportion 0.69680 0.72983 0.75884 0.78549 0.80720 0.82618 0.84331
## PC15 PC16 PC17 PC18 PC19 PC20 PC21
## Standard deviation 0.91436 0.88840 0.82337 0.78085 0.72968 0.69631 0.65241
## Proportion of Variance 0.01608 0.01518 0.01304 0.01173 0.01024 0.00932 0.00819
## Cumulative Proportion 0.85938 0.87456 0.88760 0.89932 0.90956 0.91889 0.92707
## PC22 PC23 PC24 PC25 PC26 PC27 PC28
## Standard deviation 0.63134 0.61862 0.58250 0.55471 0.54126 0.50596 0.48606
## Proportion of Variance 0.00767 0.00736 0.00653 0.00592 0.00563 0.00492 0.00454
## Cumulative Proportion 0.93474 0.94210 0.94862 0.95454 0.96017 0.96510 0.96964
## PC29 PC30 PC31 PC32 PC33 PC34 PC35
## Standard deviation 0.45105 0.42413 0.41245 0.36296 0.34904 0.33533 0.30328
## Proportion of Variance 0.00391 0.00346 0.00327 0.00253 0.00234 0.00216 0.00177
## Cumulative Proportion 0.97355 0.97701 0.98028 0.98282 0.98516 0.98732 0.98909
## PC36 PC37 PC38 PC39 PC40 PC41 PC42
## Standard deviation 0.28235 0.25340 0.23778 0.23492 0.20199 0.19520 0.18830
## Proportion of Variance 0.00153 0.00123 0.00109 0.00106 0.00078 0.00073 0.00068
## Cumulative Proportion 0.99062 0.99186 0.99295 0.99401 0.99479 0.99553 0.99621
## PC43 PC44 PC45 PC46 PC47 PC48 PC49
## Standard deviation 0.18365 0.17949 0.16946 0.16387 0.14718 0.1435 0.11607
## Proportion of Variance 0.00065 0.00062 0.00055 0.00052 0.00042 0.0004 0.00026
## Cumulative Proportion 0.99686 0.99748 0.99803 0.99854 0.99896 0.9994 0.99962
## PC50 PC51 PC52
## Standard deviation 0.10897 0.07721 0.04636
## Proportion of Variance 0.00023 0.00011 0.00004
## Cumulative Proportion 0.99984 0.99996 1.00000
#new_features <- predict(pca, newdata = df_norm) #No es necesario volver a ejecutar esta línea, es solo informativa
pca.dat <- as.data.frame(cbind(new_features, group=db$cluster))
Visualizamos los datos. Para añadir interactividad a los gráficos, usamos la biblioteca ggplotly, que nos permite acceder a información adicional al posicionarnos sobre un punto de interés.
gg2 <- ggplot(pca.dat) +
geom_point(aes(x=PC1, y=PC2, col=factor(group), text=rownames(pca.dat)), size=2) +
labs(title = "Visualizing K-Means Clusters Against First Two Principal Components") +
scale_color_brewer(name="", palette = "Set1")
## Warning: Ignoring unknown aesthetics: text
ggplotly(gg2, tooltip = c("text", "x", "y")) %>%
layout(legend = list(x=.9, y=.99))
Observamos que la mayoría de puntos están asignados a los clústers 1, 2 y 3; que están bien diferenciados. El clúster 0 parece estar formado por muy pocos puntos, que en ocasiones se entremezclan con los puntos de otros clústers.
Representamos los datos en 3D, utilizando las tres primeras componentes principales, que proporcionan algo más del 40% de la información del conjunto.
fig <- plot_ly(x= pca.dat$PC1, y= pca.dat$PC2 , z= pca.dat$PC3, type="scatter3d", mode="markers", color=factor(pca.dat$group), colors=c('red2', 'blue2', 'green3'))
fig <- fig %>% layout(title = 'Visualizing K-Means Clusters Against First Three Principal Components',
scene = list(xaxis = list(title = 'PC1'), yaxis = list(title = 'PC2'), zaxis = list(title = 'PC3')))
fig
Efectivamente, confirmamos que el clúster 0 no está bien diferenciado de los demás grupos.
Volvamos a la curva de codo de los k-vecinos. Seleccionamos un punto de corte ligeramente mayor, eps= 1.05, y ejecutamos el clustering.
db <- dbscan(df_norm, eps=1.05, minPts=53)
Mostramos un resumen del objeto devuelto tras hacer el clustering.
str(db)
## List of 3
## $ cluster: int [1:19622] 1 1 1 1 1 1 1 1 1 1 ...
## $ eps : num 1.05
## $ minPts : num 53
## - attr(*, "class")= chr [1:2] "dbscan_fast" "dbscan"
De nuevo, el modelo diferencia 4 clústers:
unique(db$cluster)
## [1] 1 2 3 0
Llevamos a cabo un análisis de componentes principales y usamos las dos primeras para visualizar los datos. Utilizamos la descomposición realizada en las secciones anteriores.
#new_features <- predict(pca, newdata = df_norm) #No es necesario volver a ejecutar esta línea, es solo informativa
pca.dat <- as.data.frame(cbind(new_features, group=db$cluster))
Visualizamos los datos. Para añadir interactividad a los gráficos, usamos la biblioteca ggplotly, que nos permite acceder a información adicional al posicionarnos sobre un punto de interés.
gg2 <- ggplot(pca.dat) +
geom_point(aes(x=PC1, y=PC2, col=factor(group), text=rownames(pca.dat)), size=2) +
labs(title = "Visualizing K-Means Clusters Against First Two Principal Components") +
scale_color_brewer(name="", palette = "Set1")
## Warning: Ignoring unknown aesthetics: text
ggplotly(gg2, tooltip = c("text", "x", "y")) %>%
layout(legend = list(x=.9, y=.99))
Podemos representar los datos en 3D, utilizando las tres primeras componentes principales, que proporcionan algo más del 40% de la información del conjunto.
fig <- plot_ly(x= pca.dat$PC1, y= pca.dat$PC2 , z= pca.dat$PC3, type="scatter3d", mode="markers", color=factor(pca.dat$group), colors=c('red2', 'blue2', 'green3'))
fig <- fig %>% layout(title = 'Visualizing K-Means Clusters Against First Three Principal Components',
scene = list(xaxis = list(title = 'PC1'), yaxis = list(title = 'PC2'), zaxis = list(title = 'PC3')))
fig
Los resultados mejoran apreciablemente.
Los clúster 1, 2 y 3 siguen estando bien diferenciados, mientras que el clúster 0 está ahora mejor definido. En la proyección sobre las tres primeras componentes principales, el clúster 0 solamente se mezcla con el clúster 1, y observamos que incluye puntos atípicos y puntos situados entre clústers.
En este análisis hemos utilizado técnicas no supervisadas para construir y evaluar modelos de segmentación que intenten capturar la estructura de grupos existentes en el conjunto de datos estudiado.
En particular, hemos explorado los siguientes modelos:
Hemos analizado los resultados de cada modelo utilizando técnicas visuales (representación gráfica de índices de calidad del modelo, visualización de los clusters sobre las variables originales, reducción de dimensionalidad y proyección sobre componentes principales) y cuantitativas (cálculo y comparación de índices de calidad del modelo, evaluación contra etiquetas supervisadas).
El modelo K-means con 3 clústers ha sido el que mejores resultados ha dado, y por tanto el que implementaríamos en un caso real.
El modelo DBSCAN con eps=1.05 y minPts=53 también ha producido buenos resultados. El modelo ha identificado cuatro clústers, tres de ellos bien definidos y con una alta densidad de puntos y uno de ellos formado por un bajo número de puntos que, en ocasiones, se mezcla con otros clústers.
Los modelos K-medoids y EM no han producido buenos resultados. Estos modelos han sido explorados utilizando distintos parámetros. En todos los casos estudiados, la evaluación de sus resultados no fue favorable.
Por último, los modelos aglomerativos de clustering han sido utilizados para explorar los datos y analizar posibles grupos en ellos.
Concluir que, en un análisis real en el que podamos aplicar reglas de negocio o del área específica de estudio, utilizaríamos la información obtenida para caracterizar y segmentar en grupos de interés. Estas técnicas también pueden ser utilizadas para extraer conocimiento de los datos, como fase previa de un análisis supervisado.